📖 本章预览
本章为预览版本,展示部分核心内容。完整内容包含详细源码解析、实战代码和面试要点,加入知识星球即可解锁全部章节。
第十一章:发版重启时线程池里的任务去哪了 — 优雅关闭
本章目标:理解 DtpLifecycleSupport 的两种关闭策略,掌握 Future.cancel(true) 的含义、awaitTermination 超时处理、InterruptedException 中断协议三个 Java 并发细节。
11.1 两难选择
应用关闭时,线程池中可能还有未完成的任务。你面临两难:
shutdownNow():立即中断所有线程,队列中的任务直接丢失shutdown():不接受新任务,但等待已提交任务完成 — 如果有任务卡住,可能无限等待
DynamicTP 通过 DtpLifecycleSupport 提供了可配置的优雅关闭策略:选择等待还是立即中断 + 限时等待兜底 + Future 取消 + 异步关闭。
11.2 internalShutdown — 核心关闭方法
@Slf4j
public class DtpLifecycleSupport {
/**
* @param waitForTasksToCompleteOnShutdown true=等待任务完成, false=立即中断
* @param awaitTerminationSeconds 最大等待秒数
*/
public static void internalShutdown(
ExecutorService executor,
String threadPoolName,
boolean waitForTasksToCompleteOnShutdown,
int awaitTerminationSeconds) {
if (Objects.isNull(executor)) {
return;
}
log.info("Shutting down ExecutorService, threadPoolName: {}",
threadPoolName);
if (waitForTasksToCompleteOnShutdown) {
// 等待模式:不接受新任务,但让队列中的任务跑完
executor.shutdown();
} else {
// 立即模式:尝试中断正在执行的任务,返回未执行的任务列表
for (Runnable remainingTask : executor.shutdownNow()) {
cancelRemainingTask(remainingTask);
}
}
// 无论哪种模式,都限时等待终止
awaitTerminationIfNecessary(executor, threadPoolName,
awaitTerminationSeconds);
}
}
11.3 cancelRemainingTask — Future 取消
protected static void cancelRemainingTask(Runnable task) {
if (task instanceof Future) {
((Future<?>) task).cancel(true);
}
}
为什么需要这一步?
shutdownNow() 返回的是未执行的 Runnable 列表。如果任务是通过 submit() 提交的,实际类型是 FutureTask。如果不调用 cancel(true):
- 调用
future.get()的线程会永久阻塞(因为任务永远不会执行了) cancel(true)会设置 Future 的取消状态,让get()抛出CancellationException- 参数
true表示允许中断正在执行的任务
11.4 awaitTerminationIfNecessary — 限时等待
private static void awaitTerminationIfNecessary(
ExecutorService executor,
String threadPoolName,
int awaitTerminationSeconds) {
if (awaitTerminationSeconds <= 0) {
return; // 不等待,直接返回
}
try {
if (!executor.awaitTermination(
awaitTerminationSeconds, TimeUnit.SECONDS)) {
// 超时了,任务还没全部完成
log.warn("Timed out while waiting for executor {} to terminate",
threadPoolName);
}
} catch (InterruptedException ex) {
// 等待过程中被中断
log.warn("Interrupted while waiting for executor {} to terminate",
threadPoolName);
Thread.currentThread().interrupt(); // 恢复中断标志
}
}
三个关键细节:
awaitTerminationSeconds <= 0时不等待,直接返回 — 适用于"fire and forget"场景
🔒 解锁完整内容
本章剩余内容需要解锁后查看
以上仅为本章部分预览内容,完整内容包含更多深度源码解析、实战代码和面试要点。
加入知识星球你将获得:
- ✅ 全部 12 章完整内容 + 持续更新
- ✅ 配套源码 + 实战项目
- ✅ 一对一答疑 + 面试辅导
- ✅ 简历优化 + 内推机会
📚 本章完整目录
以下为本章完整目录结构,加入知识星球即可解锁全部内容。