shutdown()
和 shutdownNow()
方法的区别
shutdown()
:
- 启动一个有序关闭,不再接受新任务,但会继续执行已提交的任务(包括已在队列中等待的任务)。
- 调用该方法后,线程池状态变为
SHUTDOWN
。
- 调用
shutdown()
后,isShutdown()
方法返回 true
,但 isTerminated()
方法只有在线程池里所有任务都执行完毕后才返回 true
。
shutdownNow()
:
- 尝试停止所有正在执行的任务,停止处理等待队列中的任务,并返回等待执行的任务列表。
- 调用该方法后,线程池状态变为
STOP
。
- 它会向正在执行任务的线程发送
interrupt
中断信号,所以任务需要正确处理 InterruptedException
异常。
使用场景
- 使用
shutdown()
的场景:
- 当你希望在不再接受新任务的情况下,让线程池把已提交的任务全部执行完再关闭时使用。例如,一个日志处理线程池,在应用程序关闭时,希望确保所有已提交的日志记录任务都被处理完毕,避免日志丢失。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ShutdownExample {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
final int taskNumber = i;
executorService.submit(() -> {
System.out.println("Task " + taskNumber + " is running.");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Task " + taskNumber + " is completed.");
});
}
executorService.shutdown();
}
}
- 使用
shutdownNow()
的场景:
- 当需要立即停止线程池,例如在紧急情况下,如系统出现严重错误需要马上关闭所有任务以释放资源时使用。比如,一个文件处理线程池,在检测到文件系统出现不可修复的错误时,需要立即停止所有文件处理任务。
import java.util.List;
import java.util.concurrent.*;
public class ShutdownNowExample {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
final int taskNumber = i;
executorService.submit(() -> {
System.out.println("Task " + taskNumber + " is running.");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Task " + taskNumber + " is completed.");
});
}
try {
List<Runnable> tasks = executorService.shutdownNow();
System.out.println("Tasks that were waiting to be executed: " + tasks.size());
} catch (SecurityException e) {
e.printStackTrace();
}
}
}