paradoxpenguin
paradoxpenguin

Reputation: 75

How to use Java ExecutorService threadpool for ongoing/infinite tasks?

The Java ExecutorService framework allows you to delegate a number of tasks to be performed using a managed thread pool so that N tasks can be performed X tasks at a time until complete.

My question is ... what if N is a number that is either infinite or so large as to be impractical to allocate/assign/define initially.

How can you leverage the concept of thread pooling in Java (ExecutorService) to handle more tasks than you could reasonably submit without exhausting resources.

For purposes of this answer, assume each task is self-contained and does not depend on any other task and that tasks can be completed in arbitrary order.

My initial attempt at attacking this problem involved feeding the ExecutorService Y threads at a time but I quickly realized that there's no apparent way to tell when a particular task is complete and therefore submit a new task to be executed.

I know I could write my own "ExecutorService" but I am trying to leverage the bounty of what the Java framework already provides. I'm generally in the "don't re-invent the wheel" category because greater minds than mine have already made investments for me.

Thanks in advance to anybody that can provide any insight in how to attack this type of problem.

Upvotes: 5

Views: 4051

Answers (2)

Alexei Kaigorodov
Alexei Kaigorodov

Reputation: 13535

Use java.util.concurrent.ThreadPoolExecutor with java.util.concurrent.ArrayBlockingQueue as its workQueue. This way attempt to put more tasks than the size of the queue would block.

  BlockingQueue<Runnable> workQueue=new ArrayBlockingQueue<Runnable>(100);
  ThreadPoolExecutor tpe=new ThreadPoolExecutor(5, 10, 60, TimeUnit.SECONDS, workQueue);

  while (true) {
     tpe.execute(createNewTask());
  }

Upvotes: 0

Cameron Skinner
Cameron Skinner

Reputation: 54386

You could use a CompletionService to do it. You can have one thread that seeds the service with a bunch of tasks, then as tasks complete you can add new ones.

A simple example:

final CompletionService service = new ExecutorCompletionService(Executors.newFixedThreadPool(5));
Runnable taskGenerator = new Runnable() {
    public void run() {
        // Seed the service
        for (int i = 0; i < 100; ++i) {
            service.submit(createNewTask());
        }
        // As tasks complete create new ones
        while (true) {
            Future<Something> result = service.take();
            processResult(result.get());
            service.submit(createNewTask());
        }
    }
};
new Thread(taskGenerator).start();

This uses a ThreadPoolExecutor with 5 threads to process tasks and a hand-rolled producer/consumer thread for generating tasks and processing results.

Obviously you'll want something a little smarter than while (true), you'll need to have sensible implementations of processResult and createNewTask, and this assumes that task execution is much slower than generating them or processing the results.

Hopefully this will get you on the right track.

Upvotes: 4

Related Questions