Gracefully Shutting Down a Thread Pool in Java
To gracefully shut down a Java thread pool, use ExecutorService's shutdown() to reject new tasks, awaitTermination() to wait for running tasks with optional timeout, handle exceptions, and optionally invoke shutdownNow() for forced termination, as illustrated by code examples from Dubbo3 and RocketMQ.
Gracefully closing a thread pool is an important aspect of resource management and code robustness in Java. The ExecutorService API provides methods to shut down a pool in a controlled manner.
1. Call shutdown() to reject new task submissions. Already submitted tasks continue to run, and the pool will no longer accept new work.
2. Use awaitTermination(long timeout, TimeUnit unit) to block the current thread until all tasks finish, a timeout occurs, or the thread is interrupted. The method returns true if all tasks complete within the timeout, otherwise false .
3. If tasks do not finish in time, call shutdownNow() to attempt to cancel pending tasks. This method does not block, so you may call awaitTermination again to wait for forced termination.
4. Exception handling. Capture and handle possible exceptions such as SecurityException , NullPointerException , and InterruptedException to ensure program stability during shutdown.
5. Code examples.
Dubbo3 source example:
public static void gracefulShutdown(Executor executor, int timeout) {
if (!(executor instanceof ExecutorService) || isTerminated(executor)) {
return;
}
ExecutorService es = (ExecutorService) executor;
try {
// Disable new tasks from being submitted
es.shutdown();
} catch (SecurityException | NullPointerException ex2) {
return;
}
try {
// Wait a while for existing tasks to terminate
if (!es.awaitTermination(timeout, TimeUnit.MILLISECONDS)) {
es.shutdownNow();
}
} catch (InterruptedException ex) {
es.shutdownNow();
Thread.currentThread().interrupt();
}
if (!isTerminated(es)) {
newThreadToCloseExecutor(es);
}
}RocketMQ 5.0.0 source example:
public static void shutdownGracefully(ExecutorService executor, long timeout, TimeUnit timeUnit) {
// Disable new tasks from being submitted.
executor.shutdown();
try {
// Wait a while for existing tasks to terminate.
if (!executor.awaitTermination(timeout, timeUnit)) {
executor.shutdownNow();
// Wait a while for tasks to respond to being cancelled.
if (!executor.awaitTermination(timeout, timeUnit)) {
LOGGER.warn(String.format("%s didn't terminate!", executor));
}
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted.
executor.shutdownNow();
// Preserve interrupt status.
Thread.currentThread().interrupt();
}
}Cognitive Technology Team
Cognitive Technology Team regularly delivers the latest IT news, original content, programming tutorials and experience sharing, with daily perks awaiting you.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.