Java ThreadPoolExecutor shutdown() Method

The ThreadPoolExecutor class in Java provides the shutdown() method to initiate an orderly shutdown of the executor service. This guide will cover the usage of the shutdown() method, explain how it works, and provide concise examples to demonstrate its functionality in real-world use cases.

Introduction

The shutdown() method is used to initiate an orderly shutdown of the ThreadPoolExecutor in which previously submitted tasks are executed, but no new tasks will be accepted. Once the executor has been shut down, it cannot be restarted.

shutdown Method Syntax

The syntax for the shutdown method is as follows:

public void shutdown()
  • The method does not take any parameters.
  • The method does not return any value.

Examples

Example 1: Basic Usage of shutdown()

In this example, we create a ThreadPoolExecutor, submit multiple tasks, and then shut it down using the shutdown() method.

import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

public class ShutdownExample {
    public static void main(String[] args) {
        // Create a ThreadPoolExecutor with 2 threads
        ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(2);

        // Submit tasks to the executor
        for (int i = 0; i < 5; i++) {
            final int taskNumber = i + 1;
            executor.submit(() -> {
                System.out.println("Executing task " + taskNumber + " by " + Thread.currentThread().getName());
                try {
                    Thread.sleep(2000); // Simulate task execution
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Task " + taskNumber + " completed by " + Thread.currentThread().getName());
            });
        }

        // Shutdown the executor
        executor.shutdown();
        System.out.println("Executor has been shut down.");

        // Check if the executor is terminated
        while (!executor.isTerminated()) {
            System.out.println("Executor is not terminated yet...");
            try {
                Thread.sleep(500); // Pause for a while before checking again
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.out.println("Executor has terminated.");
    }
}

Output:

Executing task 1 by pool-1-thread-1
Executing task 2 by pool-1-thread-2
Executor has been shut down.
Executing task 3 by pool-1-thread-1
Executor is not terminated yet...
Executing task 4 by pool-1-thread-2
Executor is not terminated yet...
Executing task 5 by pool-1-thread-1
Executor is not terminated yet...
Task 1 completed by pool-1-thread-1
Task 2 completed by pool-1-thread-2
Executor is not terminated yet...
Task 3 completed by pool-1-thread-1
Executor is not terminated yet...
Task 4 completed by pool-1-thread-2
Executor is not terminated yet...
Task 5 completed by pool-1-thread-1
Executor has terminated.

Example 2: Submitting Tasks After Shutdown

In this example, we attempt to submit new tasks to the ThreadPoolExecutor after it has been shut down, demonstrating that no new tasks are accepted.

import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

public class ShutdownAndSubmitExample {
    public static void main(String[] args) {
        // Create a ThreadPoolExecutor with 2 threads
        ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(2);

        // Submit tasks to the executor
        for (int i = 0; i < 3; i++) {
            final int taskNumber = i + 1;
            executor.submit(() -> {
                System.out.println("Executing task " + taskNumber + " by " + Thread.currentThread().getName());
                try {
                    Thread.sleep(1000); // Simulate task execution
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Task " + taskNumber + " completed by " + Thread.currentThread().getName());
            });
        }

        // Shutdown the executor
        executor.shutdown();
        System.out.println("Executor has been shut down.");

        // Attempt to submit a new task after shutdown
        try {
            executor.submit(() -> System.out.println("This task should not be executed."));
        } catch (Exception e) {
            System.out.println("Failed to submit task: " + e.getMessage());
        }

        // Check if the executor is terminated
        while (!executor.isTerminated()) {
            System.out.println("Executor is not terminated yet...");
            try {
                Thread.sleep(500); // Pause for a while before checking again
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.out.println("Executor has terminated.");
    }
}

Output:

Executing task 1 by pool-1-thread-1
Executing task 2 by pool-1-thread-2
Executor has been shut down.
Executing task 3 by pool-1-thread-1
Failed to submit task: ExecutorService has been shut down
Executor is not terminated yet...
Task 1 completed by pool-1-thread-1
Task 2 completed by pool-1-thread-2
Executor is not terminated yet...
Task 3 completed by pool-1-thread-1
Executor has terminated.

Example 3: Combining shutdown() with awaitTermination()

In this example, we combine the shutdown() method with the awaitTermination() method to wait for the completion of all tasks before proceeding.

import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ShutdownAndAwaitTerminationExample {
    public static void main(String[] args) {
        // Create a ThreadPoolExecutor with 3 threads
        ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(3);

        // Submit tasks to the executor
        for (int i = 0; i < 4; i++) {
            final int taskNumber = i + 1;
            executor.submit(() -> {
                System.out.println("Executing task " + taskNumber + " by " + Thread.currentThread().getName());
                try {
                    Thread.sleep(1500); // Simulate task execution
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Task " + taskNumber + " completed by " + Thread.currentThread().getName());
            });
        }

        // Shutdown the executor
        executor.shutdown();
        System.out.println("Executor has been shut down.");

        try {
            // Wait for all tasks to complete or timeout after 10 seconds
            if (executor.awaitTermination(10, TimeUnit.SECONDS)) {
                System.out.println("All tasks completed.");
            } else {
                System.out.println("Timeout elapsed before termination.");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // Confirm the termination status
        if (executor.isTerminated()) {
            System.out.println("Executor has terminated.");
        } else {
            System.out.println("Executor has not terminated yet.");
        }
    }
}

Output:

Executing task 1 by pool-1-thread-1
Executing task 2 by pool-1-thread-2
Executing task 3 by pool-1-thread-3
Executor has been shut down.
Executing task 4 by pool-1-thread-1
Task 1 completed by pool-1-thread-1
Task 2 completed by pool-1-thread-2
Task 3 completed by pool-1-thread-3
Task 4 completed by pool-1-thread-1
All tasks completed.
Executor has terminated.

Conclusion

The ThreadPoolExecutor.shutdown() method in Java is used for initiating an orderly shutdown of the executor service. By using this method, you can ensure that all previously submitted tasks are executed while preventing new tasks from being accepted.

Comments