Program does not terminate immediately when all ExecutorService tasks are done - java

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.

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.

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.
The problem is that you are not shutting down your ExecutorService. After you submit all of the jobs to the service, you should shutdown the service or the JVM will not terminate unless all of the threads in it are daemon threads. If you do not shutdown the thread-pool then any threads associated with the ExecutorService, again if not daemon, will stop the JVM from finishing. If you've submitted any tasks to a cached thread pool then you will have to wait for the threads to timeout and get reaped before the JVM will finish.
ExecutorService threadPool = Executors.newCachedThreadPool();
for(int i = 0; i < workerCount; i++) {
threadPool.execute(new Worker());
}
// you _must_ do this after submitting all of your workers
threadPool.shutdown();
Starting the threads as daemon is most likely not what you want to do because your application may stop before the tasks have completed and all of the tasks will be terminated immediately at that time. I just did a quick audit and of the 178 times we use ExecutorService classes in our production code, only 2 of them were started as daemon threads. The rest are properly shutdown.
If you need to force an ExecutorService to stop when the application is exiting then using shutdownNow() with proper handling of the thread interrupt flags is in order.

Basically on an ExecutorService you call shutdown() and then awaitTermination():
ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
while(...) {
taskExecutor.execute(new MyTask());
}
taskExecutor.shutdown();
try {
taskExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
...
}

From the javadoc for Executors.newCachedThreadPool():
Threads that have not been used for sixty seconds are terminated and removed from the cache.
It is usually a good idea to call shutdown() on an ExecutorService if you know that no new tasks will be submitted to it. Then all tasks in the queue will complete, but the service will then shut down immediately.
(Alternately, if you don't care if all the tasks complete - for example, if they are handling background calculations that are irrelevant once your main UI is gone - then you can create a ThreadFactory that sets all the threads in that pool to be daemon.)

For multi threading of ExecutorService
Solution is
threadPool.shutdown();

It is due to combination keepAliveTime=60L, timeunit=TimeUnit.SECONDS and corePoolSize=0*: when thread completes task, it does not terminate immediately, it may** wait during keepAliveTime for a new task.
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
*if core poolSize != 0 see method allowCoreThreadTimeOut() of ThreadPoolExecutor
**waiting depends on combination of current quantity of running threads in pool, corePoolSize and maximumPoolSize

Related

Is there a way to inadvertently stop the threads of an Executor?

I tried crashing the Thread of a fixed thread pool of a standard ExecutorService with this horrible code, in order to test its resilience against exceptions and errors happening inside the tasks passed to the ExecutorService:
ExecutorService executorService = Executors.newFixedThreadPool(1);
executorService.execute(() -> {
throw new RuntimeException("Trying to kill the thread");
});
Thread.sleep(100);
executorService.execute(() -> {
System.out.println("still executing");
});
but the second task prints still executing so I think the exception is being caught or the Thread instance is restarted anyway.
What is happening? Can I trust that no matter what happens inside a task (less than System.exit()) other submitted tasks will continue to be executed by the pool?
Your executor service uses a thread pool. If a thread is killed, one another will be instantiated to execute next task.
Your call Executors.newFixedThreadPool(1); set a limit on number of active threads only.
In order to stop executor service, you must call:
executorService.shutdown();

Shutting down ExecutorService

According to documentation, when shutdown() is invoked, any tasks that were already submitted (I assume via submit() or execute) will be executed. When shutdownNow() is invoked, the executor will halt all tasks waiting to be processed, as well as attempt to stop actively executing tasks.
What I would like to clarify is the exact meaning of "waiting to be processed." For example, say I have an executor, and I call execute() on some number of Runnable objects (assume all of these objects effectively ignore interruptions). I know that if I now call shutdown, all of these objects will finish executing, regardless.
However, if I call shutdownNow at this point, will it have the same effect as calling shutdown? Or are some of the objects not executed? In other words, if I want an executor to exit as fast as possible, is my best option always to call shutdownNow(), even when the Runnables passed to the executor all effectively ignore interruptions?
Let's say you have this fabulous Runnable that is not interruptible for 10 seconds once it's started:
Runnable r = new Runnable() {
#Override
public void run() {
long endAt = System.currentTimeMillis() + 10000;
while (System.currentTimeMillis() < endAt);
}
};
And you have an executor with just 1 thread and you schedule the runnable 10 times:
ExecutorService executor = Executors.newFixedThreadPool(1);
for (int i = 0; i < 10; i++)
executor.execute(r);
And now you decide to call shutdown:
The executor continues for the full 10 x 10 seconds and everything scheduled will be executed. The tasks don't see that you're shutting down their executor. shutdown can be used if you want a "short lived" executor just for a few tasks. You can immediately call shutdown and it will get cleaned up later.
Alternatively shutdownNow():
Takes 10 seconds. The already running task is attempted to be interrupted, but that obviously has no effect so it continues to run. The other 9 tasks that were still waiting in the queue are "cancelled" and returned to you as List so you could do something with them, like schedule them later. Could also take 0 seconds if the first task is not yet started. You'd get all tasks back. The method is used whenever you want to abort an entire executor.
What I would like to clarify is the exact meaning of "waiting to be processed".
It means all tasks whose run() method has not yet been called (by the executor).
If I call shutdownNow at this point, will it have the same effect as calling shutdown?
No.
Or is it possible that some of the objects will not be executed?
That is correct.
In other words, if I want an executor to exit as fast as possible, is my best option always to call shutdownNow(), even when the Runnables passed to the executor all effectively ignore interruptions?
That is correct.
Better still, recode the Runnables to pay attention to interrupts ... or put a timeout on the shutdown ...
The API for shutdownNow method says that :
There are no guarantees beyond best-effort attempts to stop processing
actively executing tasks. For example, typical implementations will
cancel via Thread.interrupt(), so any task that fails to respond to
interrupts may never terminate.
source

Java job execution multithreaded with executorservice?

How to i implement such a function ?
I have a dynamic queue which gets filled at unknown times with runnables, which have to be executed. The ExecutorService should only start a limited amount of threads, when the maximum thread size is reached, it should stop executing more threads, until one thread finishes, then the next task should be executed.
So far i came across this:
ExecutorService executor = new ThreadPoolExecutor(20, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
databaseConnectionQueue);
The ExecutorService is created before the queue is filled, and should stay alive until the queue is deleted, not when its empty, because this can happen. Can anybody help me ?
ThreadPoolExecutor will will not shutdown when it is empty. From the JavaDoc:
A pool that is no longer referenced in a program AND has no remaining
threads will be shutdown automatically.
I believe you should use FixedThreadPool (Executors.newFixedThreadPool)
As per javadoc [Executors.newFixedThreadPool]
Creates a thread pool that reuses a fixed number of threads operating
off a shared unbounded queue. At any point, at most nThreads threads
will be active processing tasks. If additional tasks are submitted
when all threads are active, they will wait in the queue until a
thread is available. If any thread terminates due to a failure during
execution prior to shutdown, a new one will take its place if needed
to execute subsequent tasks. The threads in the pool will exist until
it is explicitly shutdown.
Hope it helps. Thanks.

java Executor Service

When I create ExecutorService with below code in JAVA,can someone explain how the ExecutorService works ?
ExecutorService executor = Executors.newFixedThreadPool(400);
for (int i = 0; i < 500; i++) {
Runnable worker = new MyRunnable(10000000L + i);
executor.execute(worker);
}
I believe that there will be a single Queue of work and my for loop will add 500 Runnable tasks to this queue. Now the ExecutorService has been created with a Thread Pool of 400 threads.
So of those 500 tasks in the queue, the 400 threads in the ExecutorService will execute this 400 tasks at a time, and the remaining as slots are freed up?
Am I correct in my understanding ?
JavaDoc newFixedThreadPool
Creates a thread pool that reuses a fixed number of threads operating
off a shared unbounded queue. At any point, at most nThreads threads
will be active processing tasks. If additional tasks are submitted
when all threads are active, they will wait in the queue until a
thread is available. If any thread terminates due to a failure during
execution prior to shutdown, a new one will take its place if needed
to execute subsequent tasks. The threads in the pool will exist until
it is explicitly shutdown.
If tasks are more than number of processing threads, the tasks which haven't been picked up by threads will wait. Once the thread completes one task, it will pick-up one more waiting task.
But these thread pools (other than ForkJoinPool) are not efficient in stealing worker thread tasks.
Assume that one thread is backlog of 10 tasks to be executed and it's running first task. At that same time, some other thread in pool is idle. In this scenario, once the task is allocated a Thread, only that thread will execute the task even though other threads are idle.
ForkJoinPool differs from other kinds of ExecutorService mainly by virtue of employing work-stealing: all threads in the pool attempt to find and execute tasks submitted to the pool and/or created by other active tasks (eventually blocking waiting for work if none exist)
One more new API has been added in Java 8.
public static ExecutorService newWorkStealingPool()
Creates a work-stealing thread pool using all available processors as its target parallelism level.
Relate SE question : ThreadPoolExecutor vs ForkJoinPool: stealing subtasks

Difference between shutdown and shutdownNow of Executor Service

I want to know the basic difference between shutdown() and shutdownNow() for shutting down the Executor Service?
As far as I understood:
shutdown() should be used for graceful shutdown which means all tasks that were running and queued for processing but not started should be allowed to complete
shutdownNow() does an abrupt shut down meaning that some unfinished tasks are cancelled and unstarted tasks are also cancelled. Is there anything else which is implicit/explicit that I am missing?
P.S: I found another question on How to shutdown an executor service related to this but not exactly what I want to know.
In summary, you can think of it that way:
shutdown() will just tell the executor service that it can't accept new tasks, but the already submitted tasks continue to run
shutdownNow() will do the same AND will try to cancel the already submitted tasks by interrupting the relevant threads. Note that if your tasks ignore the interruption, shutdownNow will behave exactly the same way as shutdown.
You can try the example below and replace shutdown by shutdownNow to better understand the different paths of execution:
with shutdown, the output is Still waiting after 100ms: calling System.exit(0)... because the running task is not interrupted and continues to run.
with shutdownNow, the output is interrupted and Exiting normally... because the running task is interrupted, catches the interruption and then stops what it is doing (breaks the while loop).
with shutdownNow, if you comment out the lines within the while loop, you will get Still waiting after 100ms: calling System.exit(0)... because the interruption is not handled by the running task any longer.
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(1);
executor.submit(new Runnable() {
#Override
public void run() {
while (true) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("interrupted");
break;
}
}
}
});
executor.shutdown();
if (!executor.awaitTermination(100, TimeUnit.MICROSECONDS)) {
System.out.println("Still waiting after 100ms: calling System.exit(0)...");
System.exit(0);
}
System.out.println("Exiting normally...");
}
shutdown():
To terminate the threads inside the ExecutorService you call its shutdown() method. The ExecutorService will not shut down immediately, but it will no longer accept new tasks, and once all threads have finished current tasks, the ExecutorService shuts down. All tasks submitted to the ExecutorService before shutdown() is called, are executed.
shutdownNow():
If you want to shut down the ExecutorService immediately, you can call the shutdownNow() method. This will attempt to stop all executing tasks right away, and skips all submitted but non-processed tasks. There are no guarantees given about the executing tasks. Perhaps they stop, perhaps the execute until the end. It is a best effort attempt.
From the javadocs:
void shutdown
Initiates an orderly shutdown in which previously submitted tasks are
executed, but no new tasks will be accepted.
List<Runnable> shutdownNow()
Attempts to stop all actively executing tasks, halts the processing of
waiting tasks, and returns a list of the tasks that were awaiting
execution.
There are no guarantees beyond best-effort attempts to stop
processing actively executing tasks.
For example, typical implementations will cancel via
Thread.interrupt(), so any task that fails to respond to interrupts
may never terminate.
Returns: list of tasks that never commenced execution

Categories

Resources