当前位置: 首页 > backend >正文

Apache Ignite 生产级的线程池关闭工具方法揭秘

Apache Ignite 中用于 安全、可靠地关闭线程池(ExecutorService 的关键逻辑。我们来一步步深入理解它的设计思想和实现细节。


🧱 一、核心方法:U.shutdownNow(...)

public static void shutdownNow(Class<?> owner, @Nullable ExecutorService exec, @Nullable IgniteLogger log
)

✅ 功能:

安全地关闭一个 ExecutorService,并等待它完全停止。

🔍 参数说明:

参数含义
owner谁创建了这个线程池(用于日志记录)
exec要关闭的线程池(可能为 null
log日志组件(可能为 null

🚀 方法执行流程

1. 判空保护
if (exec != null) { ... }
  • 如果线程池是 null,直接跳过 —— 避免空指针异常

2. 立即关闭:shutdownNow()
List<Runnable> tasks = exec.shutdownNow();
  • shutdownNow() 会:
    • 尝试 中断所有正在运行的工作线程
    • 返回 尚未执行的任务列表(队列中的任务)

⚠️ 注意:它不保证正在运行的任务会被中断成功(比如任务中捕获了 InterruptedException 或未响应中断)


3. 检查是否有“幸存任务”
if (!F.isEmpty(tasks))U.warn(log, "Runnable tasks outlived thread pool executor service [...]");
  • F.isEmpty(...) 是 Ignite 的工具方法,判断集合是否为空
  • 如果返回的任务非空 → 说明有些任务还没来得及执行就被“抛弃”了
  • 打印警告日志,包含:
    • 线程池所有者(owner
    • 未执行的任务列表(帮助排查问题)

📌 这是非常重要的 可观测性设计:告诉你“哪些任务丢了”


4. 等待线程池终止
try {exec.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
}
catch (InterruptedException ignored) {warn(log, "Got interrupted while waiting for executor service to stop.");exec.shutdownNow(); // 再次尝试Thread.currentThread().interrupt(); // 恢复中断标志
}
🔹 awaitTermination(...) 的作用:
  • 阻塞当前线程,直到线程池真正终止
  • 使用 Long.MAX_VALUE 表示“无限等待” → 确保一定等到为止
🔹 为什么捕获 InterruptedException
  • 在等待过程中,当前线程可能被其他线程中断
  • 我们不能“吞掉”这个中断信号(否则上层逻辑可能无法感知中断)
  • 所以:
    1. 打个日志
    2. 再调一次 shutdownNow()(加强关闭力度)
    3. 恢复中断状态Thread.currentThread().interrupt()

✅ 这是 Java 多线程编程中的 最佳实践:不丢失中断信号


🔄 二、封装调用:stopExecutors(...)stopExecutors0(...)

private void stopExecutors(IgniteLogger log) {boolean interrupted = Thread.interrupted();try {stopExecutors0(log);}finally {if (interrupted)Thread.currentThread().interrupt();}
}

❓ 为什么要两层?

这是为了 正确处理线程中断状态

🔍 详细解释:

Thread.interrupted()
  • 是一个静态方法
  • 返回当前线程是否被中断,并清除中断标志

所以:

boolean interrupted = Thread.interrupted();

→ 拿到中断状态后,中断标志就被清除了。

finally 块中:
if (interrupted)Thread.currentThread().interrupt();

→ 如果之前是中断的,就重新设置中断标志

✅ 目的:不改变外部线程的中断状态,即“来的时候什么样,走的时候还什么样”


stopExecutors0(...):真正干活的方法
private void stopExecutors0(IgniteLogger log) {assert log != null;U.shutdownNow(getClass(), snpExecSvc, log);// 可能还有其他线程池...
}
  • 断言日志不为空
  • 调用 U.shutdownNow 关闭 snpExecSvc(可能是 striped executor 或其他线程池)
  • 可能还会关闭其他线程池(如 IO、查询、系统任务等)

🎯 三、整体作用总结

目标实现方式
安全关闭线程池shutdownNow() + awaitTermination()
防止任务丢失检查 shutdownNow() 返回的任务,打警告日志
避免中断信号丢失保存并恢复中断状态
增强可观测性记录线程池所有者、未执行任务
健壮性空值保护、异常处理、重复尝试

🧩 四、类比理解

想象你在关闭一家快递分拣中心:

  1. 广播通知:“所有人立刻停止工作!” → shutdownNow()
  2. 清点包裹:看看还有多少包裹没来得及处理 → List<Runnable> tasks
  3. 上报丢失件:如果有未处理的包裹,上报给管理层 → 打日志
  4. 等员工全部离岗:你在门口等着,直到最后一个员工离开 → awaitTermination
  5. 遇到警察拦路(中断):你被打断等待,但你记得自己还没关完门 → 恢复中断标志

✅ 五、最佳实践提炼(可用于你自己的项目)

public static void safeShutdown(ExecutorService exec, String name, Logger log) {if (exec == null) return;// 1. 尝试立即关闭List<Runnable> remainingTasks = exec.shutdownNow();// 2. 报告未执行任务if (!remainingTasks.isEmpty()) {log.warn("Tasks lost during shutdown of {}: {}", name, remainingTasks.size());}// 3. 等待终止try {if (!exec.awaitTermination(30, TimeUnit.SECONDS)) {log.warn("Executor {} didn't terminate in time, forcing...");exec.shutdownNow(); // 再试一次}} catch (InterruptedException e) {log.warn("Shutdown interrupted, forcing shutdown.");exec.shutdownNow();Thread.currentThread().interrupt(); // 恢复中断}
}

💡 你可以根据需要调整超时时间(比如不用 Long.MAX_VALUE


📌 六、一句话总结

U.shutdownNow(...) 是一个 生产级的线程池关闭工具方法,它不仅尝试关闭线程池,还关注 任务是否丢失、线程是否真正退出、中断信号是否保留,体现了 Ignite 对 稳定性、可观测性和健壮性 的高度重视。


如果你在开发中间件、框架或高可用系统,这种关闭模式 必须掌握并复用

http://www.xdnf.cn/news/17511.html

相关文章:

  • 【运维进阶】LAMPLNMP 最佳实践
  • 疯狂星期四文案网第36天运营日记
  • WNZ-20转速扭矩试验台
  • PHP request文件封装
  • 小杰python高级(three day)——matplotlib库
  • ESP32 配合上位机串口打印数据
  • Python面试题及详细答案150道(41-55) -- 面向对象编程篇
  • linux安装和使用git
  • CVE-2019-0708复刻
  • SpringBoot 实现 Excel 导入导出功能的三种实现方式
  • [激光原理与应用-240]:光学器件 - 变形镜,波前校正器
  • 数据结构:树与二叉树
  • python之浅拷贝深拷贝
  • Java Selenium 自动打开浏览器保存截图
  • DevExpress ASP.NET Web Forms v25.1新版本开发环境配置要求
  • 操作系统1.5:操作系统引导
  • OpenHarmony概述与使用
  • ttyd终端工具移植到OpenHarmony
  • 大模型工程问题
  • 用vscode 里docker显示不出有容器和镜像 ?
  • [Shell编程] Shell 编程之免交互
  • 华为watch5心率变异性测量法的底层逻辑
  • Docker部署MySQL完整指南:从入门到实践
  • MyBatis插件开发与扩展:从原理到实战的完整指南
  • 阿里发布数字人模型echomimic_v3,在视频合成的基础上支持prompt输入~
  • 机器学习 - Kaggle项目实践(1)Titanic
  • 人工智能-python-机器学习- 欠拟合与过拟合:岭回归与拉索回归的应用
  • 【安全发布】微软2025年07月漏洞通告
  • SharePlay确保最佳游戏体验
  • 基恩士 CA CNX10U 视觉连接器REPEATER CA CN or CV- C 日本原装进口