How to properly shutdown java ExecutorService - java

I have a simple java ExecutorService that runs some task objects (implements Callable).
ExecutorService exec = Executors.newSingleThreadExecutor();
List<CallableTask> tasks = new ArrayList<>();
// ... create some tasks
for (CallableTask task : tasks) {
Future future = exec.submit(task);
result = (String) future.get(timeout, TimeUnit.SECONDS);
// TASKS load some classes and invoke their methods (they may create additional threads)
// ... catch interruptions and timeouts
}
exec.shutdownNow();
After all tasks are finished (either DONE or TIMEOUT-ed), I try to shutdown the executor, but it wont stop: exec.isTerminated() = FALSE.
I suspect that some tasks that are timeouted are not properly terminated.
And yes, I know that executor's shutdown is not guaranteing anything:
There are no guarantees beyond best-effort attempts to stop
processing actively executing tasks. For example, typical
implementations will cancel via {#link Thread#interrupt}, so any
task that fails to respond to interrupts may never terminate.
My question is, is there a way to ensure those (task) threads will terminate?
The best solution I came up with, is to call the System.exit() at the end of my program, but that is plain silly.

Recommended way from Oracle API documentation page of ExecutorService:
void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
If your pool is taking more time to shutdown, you can change
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
to
while (!pool.awaitTermination(60, TimeUnit.SECONDS))
A brief summary of the shutdown related methods
shutdown():
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted.
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.
awaitTermination(long timeout, TimeUnit unit) throws InterruptedException:
Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.

Do you have control of those tasks ? i.e. are you creating those yourself ? I suspect somewhere in those a thread interrupt is being ignored e.g.
try {
....
}
catch {InterruptedException e) {
// do nothing
}
When an InterruptedException is thrown, the interrupt flag on the thread needs to be reset, otherwise the thread will not exit. See here for more info.
Unfortunately you may be using a library that doesn't obey this, in which case you can't easily circumvent this. In that case one heavyweight option is to fork off a sub process to perform the job of the Callable, and that will clear up all resources upon process exit. Heavyweight and possibly non-trivial, but reliable.

Related

Does java ExecutorService.awaitTermination() block the main thread and wait?

I've this test code:
ExecutorService executor = Executors.newFixedThreadPool(3);
executor.execute(new Runnable() {
#Override
public void run() {
try {
System.out.println("run begins");
Thread.sleep(1000);
System.out.println("run ends");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
try {
executor.awaitTermination(0L, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
executor.shutdown();
System.out.println("-----------");
I expected that, as the Runnable should sleep 1s and then ends, then executor await its termination and shutdown, finally, System.out.println("-----------"); is executed.
But the real output is:
-----------
run begins
run ends
The execution sequence doesn't make much sense to me. Seems the ExecutorService.awaitXXX and shutdown() doesn't block the main thread. The System.out.println("-----------"); was the first code line to print, and then the Runnable code.
Is this the designed behavior?
If yes, then my question is: if awaitXXXX method doesn't block the main thread, how does the main thread know when ExecutorService is done?
Seems the ExecutorService.awaitXXX and shutdown() doesn't block the
main thread
Method awaitTermination() does block the calling thread, but you've specified the timeout of 0 seconds. Quote from the javadoc:
Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.
In case if you expected that awaitTermination() will interrupt submitted tasks, then your expectation is wrong, it wouldn't do that. This method only allows you to specify the period to wait and reports whether executor is done or not.
Returns:
true if this executor terminated and false if the timeout elapsed before termination
Method shutdown() also will not interrupt any tasks that are previously submitted:
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted.
If you wish to try to interrupt submitted tasks, use 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.
Note: usage of shutdown() is a preferred approach.
From the Javadocs of ExecutorService#awaitTermination:
Blocks until all tasks have completed execution after a shutdown request
This means that awaitTermination will only work after a shutdown request so you need to call shutdown() before awaitTermination().
Furthermore, as the other answer by #Alexander Ivanchenko mentions, setting a timeout of 0L will not wait for anything and awaitTermination indicates whether the thread terminated in time via a return value. The InterruptedException is thrown if your main thread is interrupted by another thread.

Why do we need to use awaitTermination but not just shutdownNow()?

I am following the standard process that was recommended by oracle to shut down the executor services. here is the code that was recommended:
void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
I read through the descriptions for shutdown(), awaitTermination, and shutdownNow();
I understand that
shutdown() only stop submitting new threads.
awaitTermination waits for the running threads to be shutdown. Returns a value if one of completed execution, time out or current thread interrupted.
shutdownNow() use Thread.interrupt() to interrupt threads.
My question is, if I know for sure that my threads only use sleep which can be interrupted by Thread.interrupt(). Is there still a value to call awaitTermination like what oracle recommended?
I know that shutdownNow() might have a chance to not shutdown a thread, but why can't we go ahead and do something like this to force stop the threads then see if there are still threads not stoped?
pool.shutdown();
pool.shutdownNow();
try {
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
System.err.println("Pool did not terminate");
}
}
The "standard process" just tries to handle the shutdown gracefully, the premise being not to interrupt the threads when it's not necessary.
First it stops accepting new task submissions and lets the ongoing tasks finish their work. It proceeds to forceful termination only when they don't finish within the grace period.

what is the best way to wait ThreadPoolExecutor finish thread in java?

I an using ThreadPoolExecutor in java to excute multi threads, and I have to do something after threads finish, and have to wait.
So I want to ask what is the best way to do that?
Is that right I do in the way?
threadPool.shutdown();
boolean loop = true;
Integer x = threadPool.getPoolSize();
while (threadPool.getPoolSize() != 0) {
}
Shutdown will initiate an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted.
executor.shutdown();
System.out.println("All tasks submitted...No new tasks will be admitted");
However, I would strongly recommend using awaitTermination as this will allow current thread to block until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.
try {
executor.awaitTermination(3, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
EDIT:
The runState provides the main lifecyle control, taking on values:
* RUNNING: Accept new tasks and process queued tasks
* SHUTDOWN: Don't accept new tasks, but process queued tasks
* STOP: Don't accept new tasks, don't process queued tasks,
* and interrupt in-progress tasks
* TIDYING: All tasks have terminated, workerCount is zero,
* the thread transitioning to state TIDYING
* will run the terminated() hook method
* TERMINATED: terminated() has completed
The numerical order among these values matters, to allow ordered comparisons. The runState monotonically increases over time, but need not hit each state.
The transitions are:
RUNNING -> SHUTDOWN
On invocation of shutdown(), perhaps implicitly in finalize()
(RUNNING or SHUTDOWN) -> STOP
On invocation of shutdownNow()
SHUTDOWN -> TIDYING
When both queue and pool are empty
STOP -> TIDYING
When pool is empty
TIDYING -> TERMINATED
When the terminated() hook method has completed. Threads waiting in awaitTermination() will return when the state reaches TERMINATED.
Detecting the transition from SHUTDOWN to TIDYING is less straightforward than you'd like because the queue may become empty after non-empty and vice versa during SHUTDOWN state, but we can only terminate if, after seeing that it is empty, we see that workerCount is 0.
Going back to your question, when you call getPoolSize() it checks the state of the threadpool when it is in TIDYING state. Hence, I think the correct check should be against TERMINATED state. Although, the results are the same if you have not implemented terminated() method.
If you want to wait gracefully, refer to solutions in below question:
How to wait for completion of multiple tasks in Java?
If you are not using any of them ( invokeAll, CountDownLatch) and submit the jobs and waiting for executor to finish the tasks, refer to
How to forcefully shutdown java ExecutorService
Basic code snippet in this case:
void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}

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

Time limit on individual threads with ExecutorService

I have an ExecutorService managing a number of Callables. The tasks that the Callables run are mostly black box transformations and number crunching. Under certain conditions, the data being transformed will oscillate and the thread will take over an hour to finish. For comparison, most threads are completed within a minute.
It's been deteremined that the data from the long-running threads is not relevent. I would like to interrupt any thread that runs longer than a certain amount of time. What would the best way to do this?
Use a ScheduleExecutorService to schedule a task to taskFuture.cancel(true) the long running task when the timeout is reached. If the task finishes before then it won't be cancelled.
ExecutorService service = Executors.newFixedThreadPool(N);
ScheduledExecutorService canceller = Executors.newSingleThreadScheduledExecutor();
public <T> Future<T> executeTask(Callable<T> c, long timeoutMS){
final Future<T> future = service.submit(c);
canceller.schedule(new Callable<Void>(){
public Void call(){
future.cancel(true);
return null;
}
}, timeoutMS, TimeUnit.MILLI_SECONDS);
return future;
}
You could cancel the future etc as in the other answers, but you need to make sure that your threads which are "number crunching" can handle the interrupt and terminate gracefully. You say that this a black box operation - how certain are you that the interrupted status of the thread is being checked actively within the black box? If it isn't, you can't cancel it with an interrupt. The black box needs to be written with interruption in mind.
The best way for you to do this would be to introduce one more Executor. You can use a ScheduledExecutorService to cancel all long running tasks for example:
ExecutorService service = Executors.newFixedThreadPool(N);
ScheduledExecutorService canceller = Executors.newScheduledThreadPool(1);
public void executeTask(Callable<?> c){
final Future<?> future = service.submit(c);
canceller.schedule(new Runnable(){
public void run(){
future.cancel(true);
}
}, SECONDS_UNTIL_TIMEOUT, TimeUnit.SECONDS);
}
You could get a list of your corresponding Futures (that are created when you submit a Callable) together with its startup time.
Another task could then check every minute if there are some task running for more than a defined time and if so, invoke cancel(true) in the Future. Done futures would be removed off the list.
You can use this method
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout,
TimeUnit unit)
throws InterruptedException
and set the maximum timeout to one minute. If your thread takes more than that it is just aborted.
The problem is you can not kill/stop/suspend the java thread.
All are deprecated.
future.cancel will only considered before worker thread
So if the thread is stuck with any code execution and doesn't have the logic to consider the thread interruption, then execution will still continue.
This is even true for executorService.shutdown();.
The documentation says.
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.
So the only solution is to log such a situation and fix the inherent issue.
Future<?> future = executor.submit(task);
try {
future.get(15, TimeUnit.MINUTES);
} catch (InterruptedException e) {
// retry waiting. iterative approach not shown here
} catch (ExecutionException e) {
// your task exploded
} catch (TimeoutException e) {
// The task is running longer than usual
// Log it for future analysis
//If the interrupt signal is handled
//OR the task is stuck in the queue itself for a long time
//then worth calling below
future.cancel(true);
}

Categories

Resources