Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Program does not terminate immediately when all ExecutorService tasks are done

I put a bunch of runnable objects into an ExecutorService:

// simplified content of main method ExecutorService threadPool = Executors.newCachedThreadPool(); for(int i = 0; i < workerCount; i++) {     threadPool.execute(new Worker()); } 

I would expect my program/process to stop immediately after all workers are done. But according to my log, it takes another 20-30 seconds until that happens. The workers do not allocate any resources, in fact, they do nothing at the moment.

Don't get me wrong, this is not a crucial problem for me, I'm just trying to understand what is happening and I'm wondering if this is normal behavior.

like image 603
alapeno Avatar asked Nov 18 '13 20:11

alapeno


People also ask

Does ExecutorService shutdown automatically?

Using shutdown() and awaitTermination​() In general, the ExecutorService will not be automatically destroyed when there is no task to process. It will stay alive and wait for new tasks to come.

Which method of ExecutorService is called to check that all tasks are complete following shutdown?

When using an Executor, we can shut it down by calling the shutdown() or shutdownNow() methods. Although, it won't wait until all threads stop executing. Waiting for existing threads to complete their execution can be achieved by using the awaitTermination() method.

What does ExecutorService shutdown do?

Two different methods are provided for shutting down an ExecutorService. The shutdown() method will allow previously submitted tasks to execute before terminating, while the shutdownNow() method prevents waiting tasks from starting and attempts to stop currently executing tasks.

Do we need to close ExecutorService?

ExecutorService must be shutdown explicitly to reclaim the resources (CPU & Memory) occupied by threads which have already finished their job but still exist.


1 Answers

Executors.newCachedThreadPool() uses Executors.defaultThreadFactory() for its ThreadFactory. defaultThreadFactory's javadocs say that "each new thread is created as a non-daemon thread" (emphasis added). So, the threads created for the newCachedThreadPool are non-daemon. That means that they'll prevent the JVM from exiting naturally (by "naturally" I mean that you can still call System.exit(1) or kill the program to cause the JVM to halt).

The reason the app finishes at all is that each thread created within the newCachedThreadPool times out and closes itself after some time of inactivity. When the last one of them closes itself, if your application doesn't have any non-daemon threads left, it'll quit.

You can (and should) close the ExecutorService down manually via shutdown or shutdownNow.

See also the JavaDoc for Thread, which talks about daemon-ness.

like image 58
yshavit Avatar answered Sep 17 '22 17:09

yshavit