January 8, 2023 How to Shutdown a Java ExecutorService ExecutorService interface provides 3 methods shutdown(), shutdownNow() and awaitTermination() for controlling the termination of tasks submitted to executors. Learn how to use these methods under different requirements. 1. Difference between shutdown(), shutdownNow() and awaitTermination() Let us start with checking out the syntax of these methods. void shutdown(); List<Runnable> shutdownNow(); boolean awaitTermination(long timeout, TimeUnit unit); he 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 (but not started executing) to complete execution. The shutdownNow(), forcibly, attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution. This method does not wait for actively executing tasks to terminate and tries to stop them forcefully. There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. This implementation cancels tasks via Thread.interrupt(), so any task that fails to respond to interrupts may never terminate. The awaitTermination(long timeout, TimeUnit unit) blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first. Remember that awaitTermination() is invoked after a shutdown() request. 2. Using shutdown() and awaitTermination() 2.1 When to Use 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. It simply means that JVM will not terminate if we are expecting it to. This behavior is helpful in the case of web/desktop applications that perform these tasks for the infinite duration on basis of when new tasks arrive. But when we have an application that does not use the executor very frequently – and we want to reclaim the memory for other components to use – we must shutdown the executor. But we cannot shutdown the executor just like that. We must be sure that the current set of tasks submitted to the executor must be completed and shall not get killed in the process. 2.2. Example In the following example, we have scheduled 3 tasks which will be executed after 10, 20 and 30 seconds delay. After 15 seconds of scheduling the tasks, we shut down the executor but do not block the program execution as print statements get executed. At this moment, only one task has been completed that executed after 10 seconds delay. Once we call awaitTermination(), it blocks the execution and wait until all tasks are finished. Once all tasks are executed, program execution resumes, and now we can access the results of all tasks completed by the executor service. public class ShutdownExecutor { public static void main(String[] args) throws InterruptedException { ScheduledExecutorService executor = Executors.newScheduledThreadPool(3); System.out.println("WorkerTasks scheduled at : " + LocalDateTime.now()); ScheduledFuture<String> result1 = executor.schedule(new WorkerTask( "WorkerTask-1"), 10, TimeUnit.SECONDS); ScheduledFuture<String> result2 = executor.schedule(new WorkerTask( "WorkerTask-2"), 20, TimeUnit.SECONDS); ScheduledFuture<String> result3 = executor.schedule(new WorkerTask( "WorkerTask-3"), 30, TimeUnit.SECONDS); Thread.sleep(15_000); System.out.println("***********Shutting down the executor service*********"); executor.shutdown(); System.out.println("***********Tasks are partially completed*********"); System.out.println("Task-1 is done : " + result1.isDone()); System.out.println("Task-2 is done : " + result2.isDone()); System.out.println("Task-3 is done : " + result3.isDone()); System.out.println("***********Waiting for tasks to be complete*********"); executor.awaitTermination(1, TimeUnit.MINUTES); System.out.println("***********All tasks are completed now*********"); System.out.println("Task-1 is done : " + result1.isDone()); System.out.println("Task-2 is done : " + result2.isDone()); System.out.println("Task-3 is done : " + result3.isDone()); } } class WorkerTask implements Callable<String> { private final String name; public WorkerTask(String name) { this.name = name; } @Override public String call() throws Exception { System.out.println("WorkerTask [" + name + "] executed on : " + LocalDateTime.now().toString()); return "WorkerTask [" + name + "] is SUCCESS !!"; } } Output: OutputWorkerTasks scheduled at : 2022-08-07T01:56:21.446915400 WorkerTask [WorkerTask-1] executed on : 2022-08-07T01:56:31.466320300 ***********Shutting down the executor service********* ***********Tasks are partially completed********* Task-1 is done : true Task-2 is done : false Task-3 is done : false ***********Waiting for tasks to be complete********* WorkerTask [WorkerTask-2] executed on : 2022-08-07T01:56:41.466846400 WorkerTask [WorkerTask-3] executed on : 2022-08-07T01:56:51.470540700 ***********All tasks are completed now********* Task-1 is done : true Task-2 is done : true Task-3 is done : true 3. Using shutdownNow() The shutdownNow() is a hard signal to destroy ExecutorService immediately along with stopping the execution of all in-progress and queued tasks. Use this method, when we want the application to stop processing all tasks immediately. If in the previous example, we replace with executor.shutdown() to executor.shutdownNow(), we will see that as soon as shutdownNow() is invoked, program execution does not block anywhere, and task executions are stopped immediately. Here awaitTermination() does not have any effect in this case. Thread.sleep(15_000); System.out.println("***********Shutting down the executor service*********"); executor.shutdownNow(); OutputWorkerTasks scheduled at : 2022-08-07T01:57:25.427667900 WorkerTask [WorkerTask-1] executed on : 2022-08-07T01:57:35.436689400 ***********Shutting down the executor service********* ***********Tasks are partially completed********* Task-1 is done : true Task-2 is done : false Task-3 is done : false ***********Waiting for tasks to be complete********* ***********All tasks are completed now********* Task-1 is done : true Task-2 is done : false Task-3 is done : false 4. Best Practice The correct way to shutdown the executor service, as suggested in Java docs, is as follows. It shutsdown the executor service and waits for some time for submitted tasks to complete. If the running tasks do not complete in certain time, they are terminated forcefully. void shutdownAndAwaitTermination(ExecutorService pool) { // Disable new tasks from being submitted pool.shutdown(); try { // Wait a while for existing tasks to terminate if (!pool.awaitTermination(60, TimeUnit.SECONDS)) { // Cancel currently executing tasks forcefully pool.shutdownNow(); // 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 ex) { // (Re-)Cancel if current thread also interrupted pool.shutdownNow(); // Preserve interrupt status Thread.currentThread().interrupt(); } } To use this method, simply pass the ExecutorService reference to this method. ExecutorService executorService = Executors.newFixedThreadPool(1); executorService.submit(new WorkerTask("1")); executorService.submit(new WorkerTask("2")); executorService.submit(new WorkerTask("3")); shutdownAndAwaitTermination(executorService);Copied! Concurrency Java #taskcancellationadvanced java interview questions and answerscompletionserviceconcurrent-collectionsExecutorServiceexecutorservice exampleexecutorservice in javaexecutorservice javaexecutorservice tutorialsgraceful shutdowngraceful shutdown in javahow do you implement a shutdown hookhow do you run a shutdown hookjava certification trainingjava concurrency and multithreadingjava concurrency interview questionsjava executorservicejava executorservice framework nedirjava executorservice nedirjava interview questions and answersjava interview questions and answers for experiencedjava multithreading synchronizationjava shutdown hookjava shutdown hook ordermultithreading in java interview questionsshutdownshutdown hookshutdown hook threadshutdownnowterminationwhat is a shutdown hook in javawhich class and method you would use to add a shutdown hook