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 asshutdown
.
You can try the example below and replace shutdown
by shutdownNow
to better understand the different paths of execution:
- with
shutdown
, the output isStill waiting after 100ms: calling System.exit(0)...
because the running task is not interrupted and continues to run. - with
shutdownNow
, the output isinterrupted
andExiting 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 getStill 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