2

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!

Martin Vrábel
  • 788
  • 1
  • 11
  • 34
  • Call awaitTermination() in a new Thread? – VGR Jun 12 '15 at 14:30
  • This is more or less a duplicate of the following question: http://stackoverflow.com/questions/826212/java-executors-how-to-be-notified-without-blocking-when-a-task-completes – wateryan Jun 12 '15 at 14:32
  • or this one [http://stackoverflow.com/questions/10333895/timeout-for-executorservice-without-blocking-the-main-thread](http://stackoverflow.com/questions/10333895/timeout-for-executorservice-without-blocking-the-main-thread) – Amit.rk3 Jun 12 '15 at 14:36
  • @VGR Could you please be more detailed? I don't see what you mean. – Martin Vrábel Jun 12 '15 at 14:36
  • @thisismyusername I saw that question, but it is a different situation. I don't want to chain the tasks so when one completes, execute another. I just want to run all tasks at once. – Martin Vrábel Jun 12 '15 at 14:39
  • 1
    @Supermartzin Create a Runnable whose `run()` method calls awaitTermination(). Pass that Runnable to `new Thread` and call that Thread's start() method. – VGR Jun 12 '15 at 14:42
  • @VGR I see what you mean, so basically I create another single `Thread` in which I wrap my existing code. I'll try it, thanks! – Martin Vrábel Jun 12 '15 at 14:52

2 Answers2

5

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.

Community
  • 1
  • 1
Holger
  • 243,335
  • 30
  • 362
  • 661
  • 1
    Thanks, I got confused by this sentence in API documentation: `This method does not wait for previously submitted tasks to complete execution.` I assumed that all submitted and non-completed tasks will be terminated before execution but now I see that by only calling `shutdown()` I get desired behaviour. Thanks! – Martin Vrábel Jun 12 '15 at 22:22
  • I still have one more question: Is there a way how to find out when the execution queue gets empty, when last task execution ends? – Martin Vrábel Jun 12 '15 at 22:26
  • That are two different things. The queue holds the jobs which haven’t started execution yet (you could check with `getQueue().isEmpty()`). But an empty queue does not imply that there aren’t some jobs still running. You may check `getActiveCount()` but keep in mind, that’s an estimate. Having all jobs done is what `awaitTermination` implies, finishing of all jobs (plus termination of the threads). If you want to wait for the service to become idle, without terminating it, I’m afraid that that hasn’t been foreseen by the standard `ThreadPoolExecutor`. – Holger Jun 15 '15 at 08:27
0

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();
Community
  • 1
  • 1
Martin Vrábel
  • 788
  • 1
  • 11
  • 34
  • this does not make any sence, see @Holger explanation – AdamSkywalker Jun 12 '15 at 19:04
  • @AdamSkywalker I think he didn't put his question properly, he actually messed himself in awaitTermination(). His requirement was to start the tasks asynchronously and shutdown the ExecutorService once all tasks are finished. So, running his ExecutorService in new thread worked for him, and he never needed awaitTermination() as correctly explained by Holger. – hagrawal Jun 12 '15 at 20:52
  • @hagrawal it can be done in main thread without awaitTermination() call - tasks will run asynchronously and service will be shut down at the end. – AdamSkywalker Jun 12 '15 at 20:56
  • @AdamSkywalker Yes, I agree, that's why I said that he messed up with awaitTermination(), he simply needed async behavior and shutdown() was already doing its job well. – hagrawal Jun 12 '15 at 21:02
  • @hagrawal Yes, you are right guys, I got confused with one sentence in API documentation, thanks for help anyway. – Martin Vrábel Jun 12 '15 at 22:20
  • @Supermartzin No problem, we are all here to learn, help and get helped. :) – hagrawal Jun 12 '15 at 22:23