ExecutorService – shutdown(), shutdownNow() and awaitTermination​()

ExecutorService interface provides 3 methods shutdown(), shutdownNow() and awaitTermination​() for controlling the termination of tasks submitted to executor. Learn to use these methods under different requirements.

1. Difference between shutdown(), shutdownNow() and awaitTermination​() APIs

void shutdown();

List<Runnable> shutdownNow();

boolean	awaitTermination(long timeout, TimeUnit unit);
  • 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.
  • 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.
    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.
  • 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.
  • In short, shutdown() means the executor service takes no more incoming tasks.
  • Remember that awaitTermination() is invoked after a shutdown() request.

2. Using ExecutorService shutdown() and awaitTermination​() together

In general, the ExecutorService will not be automatically destroyed when there is not task to process. It will stay alive and wait for new tasks to do. It simply means that JVM will not terminate if we are expecting it to be.

This behavior is helpful in case of web/desktop application which perform these tasks for infinite duration on basis of when new tasks arrive.

But when have an application which does not use 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 executor must be completed and shall not get killed in process.

To allow the previously submitted tasks to complete; and do not allow new tasks to executor; and wait for submitted tasks to complete – we have to use shutdown() with awaitTermination​().

In this java program, we have scheduled 3 tasks which will be executed after 10,20,30 seconds delay. After 15 seconds, we shut down the executor but does not block the program execution as print statements gets executed. At this moment, only one task has been completed.

Once we call awaitTermination(), it blocks the execution now 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 executor.

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public class Main 
{
	public static void main(String[] args) throws InterruptedException, ExecutionException 
	{
		ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
		
		LocalDateTime now = LocalDateTime.now();
	 
	    System.out.println("WorkerTasks scheduled at : "+ LocalDateTime.now());
		
	    ScheduledFuture<String> result1 = executor.schedule(new WorkerTask("WorkerTask-1"), 
				Duration.between(now, now.plusSeconds(10)).toMillis(), 
				TimeUnit.MILLISECONDS);

	    ScheduledFuture<String> result2 = executor.schedule(new WorkerTask("WorkerTask-2"), 
				Duration.between(now, now.plusSeconds(20)).toMillis(), 
				TimeUnit.MILLISECONDS);
	    
	    ScheduledFuture<String> result3 = executor.schedule(new WorkerTask("WorkerTask-3"), 
				Duration.between(now, now.plusSeconds(30)).toMillis(), 
				TimeUnit.MILLISECONDS);
	    
	    //Wait for 15 seconds
	    Thread.sleep(15_000);
	    
		executor.shutdown();
		
		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.HOURS);
		
		System.out.println("***********All tasks are completed nows*********");
		
		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 !!";
	}
}

Program output.

WorkerTasks scheduled at : 2019-05-23T18:07:47.921

WorkerTask [WorkerTask-1] executed on : 2019-05-23T18:07:57.944

Task-1 is done : true
Task-2 is done : false
Task-3 is done : false

***********Waiting for tasks to be complete*********

//Program execution is blocked here

WorkerTask [WorkerTask-2] executed on : 2019-05-23T18:08:07.942
WorkerTask [WorkerTask-3] executed on : 2019-05-23T18:08:17.942

***********All tasks are completed nows*********

Task-1 is done : true
Task-2 is done : true
Task-3 is done : true

2. Using shutdownNow()

shutdownNow() is a hard signal to destroy the ExecutorService immediately along with stopping the execution of all in-progress and queued tasks. Use this method, when we want application to stop processing all tasks immediately.

If in 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 effect in this case.

public class Main 
{
	public static void main(String[] args) throws InterruptedException, ExecutionException 
	{
		ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
		
		LocalDateTime now = LocalDateTime.now();
	 
	    System.out.println("WorkerTasks scheduled at : "+ LocalDateTime.now());
		
	    ScheduledFuture<String> result1 = executor.schedule(new WorkerTask("WorkerTask-1"), 
				Duration.between(now, now.plusSeconds(10)).toMillis(), 
				TimeUnit.MILLISECONDS);

	    ScheduledFuture<String> result2 = executor.schedule(new WorkerTask("WorkerTask-2"), 
				Duration.between(now, now.plusSeconds(20)).toMillis(), 
				TimeUnit.MILLISECONDS);
	    
	    ScheduledFuture<String> result3 = executor.schedule(new WorkerTask("WorkerTask-3"), 
				Duration.between(now, now.plusSeconds(30)).toMillis(), 
				TimeUnit.MILLISECONDS);
	    
	    //Wait for 15 seconds
	    Thread.sleep(15_000);
	    
		executor.shutdownNow();
	
		//Does not have any effect
		executor.awaitTermination(1, TimeUnit.HOURS);
		
		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());
	}
}

Program output.

WorkerTasks scheduled at : 2019-05-23T18:34:29.523

WorkerTask [WorkerTask-1] executed on : 2019-05-23T18:34:39.551

Task-1 is done : true
Task-2 is done : false
Task-3 is done : false

Drop me your questions related to shutdown(), shutdownNow() and awaitTermination​() APIs of ExecutorService interface and how to use them correctly.

Happy Learning !!

Ref:

Java Docs

Was this post helpful?

Join 7000+ Fellow Programmers

Subscribe to get new post notifications, industry updates, best practices, and much more. Directly into your inbox, for free.

Leave a Comment

HowToDoInJava

A blog about Java and its related technologies, the best practices, algorithms, interview questions, scripting languages, and Python.