shutdown和shutdownnow的核心区别在于对待正在执行或等待执行的任务策略不同:shutdown会停止接收新任务,但会等待已提交的任务(包括正在执行的和队列中等待的)全部完成后再关闭线程池;而shutdownnow会尝试立即停止所有正在执行的任务,并暂停处理等待中的任务,同时返回那些尚未开始执行的任务列表。简单来说,前者是“优雅退出”,后者是“强制中断”。

shutdown如何确保任务不丢失?
shutdown方法通过设置内部状态为STOP之前的RUNNING或SHUTDOWN状态来工作。调用后,线程池不再接受任何新任务(execute方法会抛出异常),但对于已经提交到任务队列中的任务,它会继续处理直到队列为空。正在执行的任务不会被中断,它们会运行完毕。这是实现资源清理和数据持久化的首选方式。

import java.util.concurrent.*;
public class ShutdownExample {
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(2);
// 提交一个耗时任务
executor.submit(() -> {
System.out.println("Task 1 running...");
try { Thread.sleep(2000); } catch (InterruptedException e) {}
System.out.println("Task 1 finished.");
});
// 提交另一个任务
executor.submit(() -> System.out.println("Task 2 submitted and waiting"));
// 调用 shutdown
executor.shutdown();
// 尝试提交新任务会失败
try {
executor.submit(() -> System.out.println("New task"));
} catch (RejectedExecutionException e) {
System.out.println("New task rejected: " + e.getMessage());
}
// 等待终止
if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
System.out.println("Tasks did not finish in time.");
} else {
System.out.println("All tasks completed gracefully.");
}
}
}
shutdownNow如何中断正在运行的任务?
shutdownNow首先将线程池状态设为TIDYING,然后调用所有工作线程的interrupt()方法。如果任务检查了中断状态(如Thread.sleep、BlockingQueue.take等),它们会抛出InterruptedException并提前结束。对于未开始执行的任务,它们会被从队列中移除并放入返回的List<runnable></runnable>中,以便调用者可以重新处理或记录。注意,如果任务没有响应中断,它可能仍会继续运行直到自然结束。
立即学习“Java免费学习笔记(深入)”;

import java.util.List;
import java.util.concurrent.*;
public class ShutdownNowExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(2);
// 提交一个可中断的任务
Future<?> future = executor.submit(() -> {
System.out.println("Task running, sleeping...");
try { Thread.sleep(5000); } catch (InterruptedException e) {
System.out.println("Task interrupted!");
throw new RuntimeException("Interrupted", e);
}
return "Done";
});
// 提交一个简单任务
executor.submit(() -> System.out.println("Simple task"));
// 调用 shutdownNow
List<Runnable> notExecuted = executor.shutdownNow();
System.out.println("Tasks not executed: " + notExecuted.size());
// 注意:正在运行的任务可能不会立即停止
try {
future.get(); // 获取结果或异常
} catch (Exception e) {
System.out.println("Future exception: " + e.getCause().getMessage());
}
executor.shutdown(); // 最终关闭
}
}
当任务忽略中断时,shutdownNow的实际效果是什么?
如果提交的任务内部没有检查Thread.interrupted()或捕获InterruptedException,例如执行纯计算逻辑或不阻塞的操作,那么即使调用了shutdownNow,该任务也会继续运行直到完成。这是因为shutdownNow只是发送中断信号,并不能强制杀死线程。在这种情况下,shutdownNow只能阻止新任务的提交和队列中等待任务的处理,但对正在执行且不响应中断的任务无效。开发者必须确保关键任务能正确响应中断信号,否则shutdownNow无法达到立即停止的目的。


















