ExecutorService - How to wait for completition of all tasks in non-blocking style

1.6k views Asked by At

I am using ExecutorService in Java web server application for executing some computational tasks in parallel style and then calling shutdown() with awaitTermination() to wait for all tasks to be done. Whole computation can sometimes take dozens of minutes.

The thing is awaitTermination() method blocks the main thread until timeout elapsed (or interrupted) but I just want to start the tasks and immediatedly respond to client and after competition of all tasks shutdown the service (following conventions to always close the thread pool).

So my question, is there a way how I can be notified when all tasks are done so I could call the shutdown() method? Listener or something..

Thanks!

2

There are 2 answers

3
Holger On BEST ANSWER

You are trying to solve a problem that doesn’t exist. Consider the documentation of ExecutorService.shutdown():

Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. …

This method does not wait for previously submitted tasks to complete execution.

In other words, just calling shutdown() does already everything you want

  • It finishes all previously submitted tasks
  • It initiates a shutdown
  • It does not wait

The only obstacle is that you are calling awaitTermination despite the fact that you don’t want to wait, which has a trivial solution: don’t call awaitTermination.

The confusion arises because in your question you are asking “how I can be notified when all tasks are done so I could call the shutdown() method” but that is in contradiction to what you are actually doing in the code. You are calling awaitTermination after shutDown so you are not waiting in order to initiate the shutdown, but initiating the shutdown first and waiting for its completion then, which is the purpose of awaitTermination, waiting for the completion of the shutdown.


To put it in one sentence, just call shutDown after submission in order to shutdown the service after completion of all submitted jobs and don’t call awaitTermination unless you really want to wait for the termination.

6
Martin Vrábel On

Thanks to comment from VGR I solved my problem with creating yet another Thread in which I wrapped my existing code like this:

Thread thread = new Thread(() -> {
    ExecutorService service = Executors.newCachedThreadPool();

    collection.forEach(item -> service.submit(() -> {
            // some computational work
        });

    try {
        service.shutdown()
        service.awaitTermination(2, TimeUnit.HOURS);
    catch (InterruptedException iEx) {
        // handle exception
    }
});

thread.start();

return ResponseToClient();