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.pswp.cn/pingmian/92852.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/92852.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/92852.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unity:GUI笔记(一)——文本、按钮、多选框和单选框、输入框和拖动条、图片绘制和框绘制

写在前面&#xff1a;写本系列(自用)的目的是回顾已经学过的知识、记录新学习的知识或是记录心得理解&#xff0c;方便自己以后快速复习&#xff0c;减少遗忘。主要是唐老师的课程。一、重要参数、文本、按钮GUI相关代码需要写在private void OnGUI()中。该函数每帧执行&#x…

wordpress从wp_nav_menu中获取菜单项

从wp_nav_menu中获取菜单项&#xff0c;然后检查这些菜单项是否对应分类(Category)&#xff0c;并输出这些分类的ID。 以下是完整的代码实现&#xff1a; <?php // 获取指定菜单位置的菜单项 $menu_items wp_get_nav_menu_items(wodepress); // wodepress 是菜单位置的名…

第4章 程序段的反复执行2 while语句P128练习题(题及答案)

&#xff08;&#xff08;1&#xff09;阅读程序#include <bits/stdc.h> using namespace std; //汤永红 int main(){int n,s0;cin >> n;while(n){s s * 10 n % 10;n / 10;}cout << s << endl;return 0; }分别输入&#xff1a;0 1024 1234567890输出…

图解软件系统组成

这是基于 ​​PlantUML​​ 绘制的软件系统组成部分思维导图&#xff0c;聚焦技术路线与文件类型的对应关系&#xff0c;采用分层架构展示核心模块&#xff1a;startmindmap * **软件系统组成部分*** **一、核心技术栈*** 后端技术* 技术路线: Python Web 框架* 文件类型: .py …

【传奇开心果系列】Flet框架实现的多人访问web数据表高并发前后端自定义框架模板

Flet框架实现的多人访问web数据表高并发前后端自定义框架模板一、效果展示截图二、应用场景介绍1. **多用户实时协作**2. **产品管理**3. **数据可视化**三、特色说明1. **实时通信**2. **高性能**3. **用户友好的界面**4. **日志记录**5. **安全性**四、总结五、源码下载地址六…

农业智慧大屏系统 - Flask + Vue实现

下面我将实现一个完整的农业智慧大屏系统&#xff0c;使用Flask作为后端框架&#xff0c;前端使用Vue.js结合ECharts进行数据可视化展示。 设计思路 前端部分&#xff1a; 使用Vue.js构建响应式界面 使用ECharts实现各类农业数据可视化 使用CSS Grid布局实现大屏适配 后端…

Linux中Https配置与私有CA部署指南

Linux中Https配置与私有CA部署指南 一、HTTPS 核心概念特性HTTPHTTPS协议明文传输HTTP SSL/TLS端口80443加密未加密数据加密二、SSL/TLS 握手流程 Client → Server ClientHello&#xff1a;支持哪些版本、支持哪些加密算法&#xff0c;随机生成一组32字节数据 random_c Serve…

【软考架构】主流数据持久化技术框架

JDO与JPA JDO&#xff08;Java Data Objects&#xff09;和JPA&#xff08;Java Persistence API&#xff09;都是Java中用于对象持久化的规范&#xff0c;但它们在设计目标、技术背景和应用场景上存在显著区别。以下是两者的核心对比&#xff1a;1. 规范背景与维护方 JDO&…

服务日志、监控

服务怎么做监控和告警使用 Prometheus 和 Grafana 来实现整个微服务集群的监控和告警&#xff1a;Prometheus&#xff1a;Prometheus 是一个开源的监控系统&#xff0c;具有灵活的数据模型和强大的查询语言&#xff0c;能够收集和存储时间序列数据。它可以通过 HTTP 协议定期拉…

秋招笔记-8.12

我决定从今天开始&#xff0c;在每天的学习内容中加入算法的内容&#xff0c;大致分布时间的话&#xff0c;假设我一天可以学习八个小时&#xff0c;那算法两个小时&#xff0c;八股三个小时&#xff0c;项目三个小时这样的分布差不多吧。之所以还是需要做做笔试一是为了应对面…

【从0带做】基于Springboot3+Vue3的校园表白墙系统

大家好&#xff0c;我是武哥&#xff0c;最近给大家手撸了一个基于SpringBoot3Vue3的校园表白墙系统&#xff0c;可用于毕业设计、课程设计、练手学习&#xff0c;系统全部原创&#xff0c;如有遇到网上抄袭站长的&#xff0c;欢迎联系博主~ 资料获取方式 请点开作者头像看下…

【Linux系列】服务器 IP 地址查询

博客目录一、hostname 命令&#xff1a;简单高效的 IP 查询工具命令详解实际应用技巧注意事项二、ip 命令&#xff1a;新一代网络配置全能工具基本用法在服务器管理和网络运维中&#xff0c;快速准确地获取服务器的 IP 地址是一项基本但至关重要的技能。无论是进行远程连接、配…

【完美解决】在 Ubuntu 24.04 上为小米 CyberDog 2 刷机/交叉编译:终极 Docker 环境搭建指南

摘要 本文旨在为广大开发者提供一份在非官方推荐的 Ubuntu 24.04 系统上&#xff0c;成功为小米机器狗 CyberDog 2 进行刷机和交叉编译的终极解决方案。通过层层排查 setup.sh 依赖缺失、No devices to flash 以及交叉编译 Segmentation fault 等疑难杂症&#xff0c;我们发现根…

XX生产线MES系统具体实施方案

一、系统架构设计1. 整体架构图2. 技术组件清单模块技术选型部署要求应用服务Spring Boot 3.2 Spring CloudKubernetes Pod (4C8G)实时通信Kafka 3.6 WebSocket3节点集群工业协议Eclipse Milo (OPC UA)独立服务器 (2C4G)数据库PostgreSQL 15 TimescaleDB 2.10SSD存储, 主从复…

Go语言实战案例:使用模板渲染HTML页面

在 Web 开发中&#xff0c;身份验证是一个绕不开的话题。传统的 Session 机制依赖服务器存储用户状态&#xff0c;而在微服务、分布式架构下&#xff0c;这种方式可能会导致状态同步困难。 JWT&#xff08;JSON Web Token&#xff09;是一种无状态的、跨平台的身份验证解决方案…

@RequestMapping接收文件格式的形参(方法参数)

需求&#xff1a;将文件上传到OSS&#xff0c;忽略域名与路径&#xff0c;将文件名以 “img1.png,img2.png,img3.png”保存到数据库中 1、先看结果 后端要接收postman传递的file文件2、SpringBoot接收参数方式 很显然&#xff0c;上面postman上传的地方可以传入多个文件&#x…

【数据分享】2020-2022年我国乡镇的逐日最高气温数据(Shp/Excel格式)

之前我们分享过2020—2022年中国0.01分辨率逐日最高气温栅格数据&#xff08;可以查看之前的文章获悉详情&#xff09;&#xff01;该数据是研究者张凌, 胡英屹等发布在国家冰川冻土沙漠科学数据中心平台上的高分辨最高气温数据。很多小伙伴拿到数据后反馈栅格数据不太方便使用…

为什么C++主函数 main 要写成 int 返回值 | main(int argc, char* argv[]) 这种写法是什么意思?

主函数 main 要写成 int 返回值&#xff1f;main(int argc, char* argv[]) 为什么里面没有 cin 也能读到数据&#xff0c;数据是怎么传进去的&#xff1f;本文将一步步回答这些问题。1. 为什么 main 要写成 intC 标准&#xff08;ISO/IEC 14882&#xff09;规定&#xff0c;mai…

【oracle闪回查询】记录字段短时间被修改的记录

SELECT versions_starttime, versions_endtime, versions_operation, versions_xid, [字段1], [字段2] – 替换为实际字段名 FROM 表名 VERSIONS BETWEEN TIMESTAMP SYSTIMESTAMP - INTERVAL ‘15’ MINUTE AND SYSTIMESTAMP --15分钟内 WHERE id ‘目标ID’ – 指定记录的唯…

【软考中级网络工程师】知识点之 IP 组播技术:从原理到实战

目录一、IP 组播技术概述1.1 什么是 IP 组播1.2 IP 组播与其他传输方式对比二、IP 组播地址详解2.1 IPv4 组播地址范围及分类2.2 特殊 IPv4 组播地址示例2.3 IPv6 组播地址结构与特点2.4 IP 组播地址与 MAC 地址的映射关系三、IP 组播协议剖析3.1 IGMP 协议深度解析3.2 PIM 协议…