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

Java线程池管理最佳实践(设计模式)

引言

在多线程编程中,线程池是一种非常重要的资源管理工具。合理使用线程池可以显著提高系统性能,避免频繁创建和销毁线程带来的开销。今天,我将为大家深入分析一个实用的ThreadPoolManager实现,它来自com.kingdee.eas.util包,是一个优秀的线程池管理工具类。

核心设计解析

1. 单例模式实现

private static final ThreadPoolManager INSTANCE = new ThreadPoolManager();public static ThreadPoolManager getInstance() {return INSTANCE;
}

ThreadPoolManager采用饿汉式单例模式,确保全局只有一个线程池实例。这种设计避免了重复创建线程池带来的资源浪费,也便于统一管理。

2. 自动计算线程池大小

static {int cpus = Runtime.getRuntime().availableProcessors();if (cpus <= 0) {logger.error("无法获取 CPU 核心数,默认使用 2");cpus = 2;}AVAILABLE_PROCESSORS = cpus;
}private ThreadPoolManager() {int poolSize = AVAILABLE_PROCESSORS * 2;poolSize = Math.max(2, poolSize); // 至少保留 2个线程this.executor = Executors.newFixedThreadPool(poolSize);registerShutdownHook();
}

这段代码展示了几个优秀实践:

  1. 根据CPU核心数动态计算线程池大小(核心数×2)

  2. 设置最小线程数为2,确保低配机器也能运行

  3. 使用静态初始化块预先计算CPU核心数,避免重复计算

3. 优雅的关闭机制

private void registerShutdownHook() {Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {@Overridepublic void run() {logger.error("【Shutdown Hook】开始关闭线程池...");ThreadPoolManager.this.shutdown();logger.error("【Shutdown Hook】线程池已关闭");}}));
}public void shutdown() {if (!executor.isShutdown()) {executor.shutdown(); // 不再接受新任务try {if (!executor.awaitTermination(800, java.util.concurrent.TimeUnit.MILLISECONDS)) {logger.error("线程池未完全关闭,尝试强制关闭...");executor.shutdownNow();}} catch (InterruptedException e) {executor.shutdownNow();Thread.currentThread().interrupt();}}
}

关闭机制的设计亮点:

  1. 注册JVM关闭钩子,确保应用退出时自动关闭线程池

  2. 分阶段关闭:先尝试优雅关闭,超时后强制关闭

  3. 正确处理中断异常,恢复中断状态

使用示例

使用这个线程池管理器非常简单:

// 提交任务
ThreadPoolManager.getInstance().submit(() -> {// 你的任务代码
});// 手动关闭(通常不需要,因为有shutdown hook)
// ThreadPoolManager.getInstance().shutdown();

最佳实践建议

  1. 任务设计:确保提交的任务是线程安全的,避免共享可变状态

  2. 异常处理:在任务内部处理好异常,避免任务因异常而终止

  3. 监控:可以扩展此类,添加监控线程池状态的功能

  4. 动态调整:对于更复杂的场景,可以考虑使用ThreadPoolExecutor直接创建线程池,以便动态调整参数

可能的改进方向

  1. 配置化:将线程池大小等参数改为可配置的,而不是硬编码

  2. 多样化线程池:支持创建不同类型的线程池(如缓存线程池、定时线程池等)

  3. 监控扩展:添加线程池状态监控和报警功能

  4. 任务队列限制:固定线程池默认使用无界队列,可以考虑改为有界队列避免OOM

总结

这个ThreadPoolManager实现简洁而实用,涵盖了线程池管理的核心关注点:初始化、任务提交和优雅关闭。特别适合作为中小型应用的默认线程池管理方案。通过学习这个实现,我们可以深入理解Java线程池的最佳实践。

完整代码

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;import org.apache.log4j.Logger;public class ThreadPoolManager {private static final Logger logger = Logger.getLogger("com.kingdee.eas.util.ThreadPoolManager");private static final ThreadPoolManager INSTANCE = new ThreadPoolManager();private final ExecutorService executor;private static final int AVAILABLE_PROCESSORS;static {int cpus = Runtime.getRuntime().availableProcessors();if (cpus <= 0) {logger.error("无法获取 CPU 核心数,默认使用 2");cpus = 2;}AVAILABLE_PROCESSORS = cpus;}// 私有构造函数private ThreadPoolManager() {// 根据当前CPU核心数,创建合适的核心线程数int poolSize = AVAILABLE_PROCESSORS * 2;poolSize = Math.max(2, poolSize); // 至少保留 2个线程this.executor = Executors.newFixedThreadPool(poolSize);registerShutdownHook();}public static ThreadPoolManager getInstance() {return INSTANCE;}public void submit(Runnable task) {executor.submit(task);}// 注册 JVM 关闭钩子,private void registerShutdownHook() {Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {@Overridepublic void run() {logger.error("【Shutdown Hook】开始关闭线程池...");ThreadPoolManager.this.shutdown(); // 调用关闭方法logger.error("【Shutdown Hook】线程池已关闭");}}));}/*** 关闭线程池(建议在应用退出前调用)*/public void shutdown() {if (!executor.isShutdown()) {executor.shutdown(); // 不再接受新任务try {// 最多等待一段时间让任务完成if (!executor.awaitTermination(800, java.util.concurrent.TimeUnit.MILLISECONDS)) {logger.error("线程池未完全关闭,尝试强制关闭...");// 强制中断正在执行的任务executor.shutdownNow();}} catch (InterruptedException e) {// 被中断时恢复中断状态executor.shutdownNow();Thread.currentThread().interrupt();}}}
}

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

相关文章:

  • 【JavaSE】异常处理学习笔记
  • 对比RFX2401C:AT2401C功率放大器的性价比与PIN兼容方案
  • 智汇云舟携最新无人机2D地图快速重建技术亮相广西国际矿业展览会
  • 蛋白质研究用蛋白酶购买渠道推荐
  • 深入理解C# Socket编程中的BeginConnect异步连接方法
  • vscode中launch.json、tasks.json的作用及实例
  • 苹果iOS应用ipa文件进行签名后无法连接网络,我们该怎么解决
  • 单链表反序实现
  • AI笔记 - 模型调试 - 调试方式
  • 日常踩坑-pom文件里jdbc配置问题
  • buunctf Crypto-[WUSTCTF2020]情书1
  • 模具制造业数字化转型:精密模塑,以数字之力铸就制造基石
  • 5月28日星期三今日早报简报微语报早读
  • AI任务相关解决方案1-基于NLP的3种模型实现实体识别,以及对比分析(包括基于规则的方法、CRF模型和BERT微调模型)
  • SQL进阶之旅 Day 6:数据更新最佳实践
  • STP协议:如何消除网络环路风暴
  • 【分治】翻转对
  • jsrpc进阶模式 秒杀js前端逆向问题 burp联动进行爆破
  • 【JavaEE】Spring事务
  • c++设计模式-介绍
  • 摩尔条纹 原理以及matlab 实现
  • 数据结构 - 树的遍历
  • 【JavaEE】-- 网络原理
  • NetLink
  • SNTP在电力系统通信中的应用
  • C# NX二次开发-查找连续倒圆角面
  • GB/T 36140-2018 装配式玻纤增强无机材料复合保温墙体检测
  • 【第2章 绘制】2.7 路径、描边与填充
  • 【C++进阶篇】哈希表的模拟实现(赋源码)
  • WSL中ubuntu通过Windows带代理访问github