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

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.dtcms.com/a/325445.html

相关文章:

  • 【C++】封装哈希表模拟实现unordered_set和unordered_map
  • 【10】微网优联——微网优联 嵌入式技术一面,校招,面试问答记录
  • 【Linux让旧电脑重获新生的奇妙魔法】
  • 【k8s】k8s安装与集群部署脚本
  • Godot ------ 平滑拖动03
  • 量子神经网络:从NISQ困境到逻辑比特革命的破局之路
  • Day 37:早停策略和模型权重的保存
  • C语言指针(四):字符指针、数组指针与函数指针的实战指南
  • Unity大型场景性能优化全攻略:PC与安卓端深度实践 - 场景管理、渲染优化、资源调度 C#
  • 在Mac 上生成GitLab 的SSH 密钥并将其添加到GitLab
  • 在 .NET Core 5.0 中启用 Gzip 压缩
  • AI时代基于云原生的 CI/CD 基础设施 Tekton
  • Redis Sentinel 中 `sentinel resolve-hostnames yes` 的必要性解析
  • C#图形库SciChart与ScottPlot及LiveCharts2对比
  • Linux客户端利用MinIO对服务器数据进行同步
  • 掌握while循环:C语言编程基础
  • Unity跨平台性能优化全攻略:PC与安卓端深度优化指南 - CPU、GPU、内存优化 实战案例C#
  • 《番外:Veda的备份,在某个未联网的旧服务器中苏醒……》
  • 扩展运算符...作用介绍
  • 关系型数据库:原理、演进与生态全景——从理论基石到云原生的深度巡礼
  • 国内 Mac 开启 Apple Intelligence 教程
  • 深入浅出JVM:Java虚拟机的探秘之旅
  • 第2节 PyTorch加载数据
  • 关系操作符详解与避坑指南
  • 软件编程2-标准IO
  • Maxscript实现在物体表面均匀散布的4种主流算法
  • C# 异步编程(计时器)
  • 大模型提示词工程实践:大语言模型文本转换实践
  • 实战:用 PyTorch 复现一个 3 层全连接网络,训练 MNIST,达到 95%+ 准确率
  • 软考高级资格推荐与选择建议