JavaEE——多线程(5)

Java线程池详解

Java 线程池是管理线程生命周期、控制并发度的核心组件,基于 “池化思想” 减少线程创建 / 销毁的开销,优化系统资源利用率,同时提供任务队列、拒绝策略等机制,确保并发编程的稳定性和可维护性。

1.为什么需要线程池

直接创建线程存在以下问题:

  1. 资源开销大:线程创建 / 销毁需要操作系统分配内核资源(如 PCB),频繁操作会消耗大量 CPU 和内存;
  2. 并发失控:无限制创建线程会导致 CPU 上下文切换频繁,甚至 OOM(线程栈占用内存,默认 1MB);
  3. 管理复杂:手动维护线程的创建、执行、销毁,难以处理任务队列、异常捕获等场景。

线程池的核心优势:

  • 复用线程,减少创建 / 销毁开销;
  • 控制最大并发数,避免资源耗尽;
  • 提供任务缓冲队列,削峰填谷;
  • 支持任务拒绝、线程监控、定时执行等高级功能。

2.核心组件 ThreedPoolExecutor

Java 线程池的底层实现是java.util.concurrent.ThreadPoolExecutor,所有线程池(如Executors创建的)本质都是它的封装。

1.核心构造方法

public ThreadPoolExecutor( int corePoolSize, // 核心线程数(常驻线程,即使空闲也不销毁) int maximumPoolSize, // 最大线程数(核心线程+临时线程的总上限) long keepAliveTime, // 临时线程空闲存活时间 TimeUnit unit, // keepAliveTime的时间单位(如TimeUnit.SECONDS) BlockingQueue<Runnable> workQueue, // 任务阻塞队列(核心线程满时存任务) ThreadFactory threadFactory, // 线程工厂(用于创建线程,可自定义命名、优先级) RejectedExecutionHandler handler // 拒绝策略(任务队列满+线程达最大数时的处理方式) ) {}

2.核心参数详解

1)核心线程数(corePoolSize)
  • 线程池的 “常驻线程”,即使空闲也不会销毁(除非设置allowCoreThreadTimeOut(true));
  • 任务提交时,若核心线程未满,直接创建核心线程执行任务。
(2)最大线程数(maximumPoolSize)
  • 线程池能容纳的最大线程数(核心线程 + 临时线程);
  • 核心线程满且队列满时,会创建临时线程执行任务;
  • 临时线程空闲超过keepAliveTime会被销毁,恢复到核心线程数。
(3)任务队列(workQueue)
  • 核心线程满时,新任务会进入队列等待;
  • 必须使用阻塞队列(BlockingQueue),支持线程安全的入队 / 出队操作,常用实现:
    • LinkedBlockingQueue:无界队列(默认容量Integer.MAX_VALUE),风险:任务堆积导致 OOM;
    • ArrayBlockingQueue:有界队列(需指定容量),推荐使用,避免 OOM;
    • SynchronousQueue:无缓冲队列,任务必须立即被线程执行(无线程则创建临时线程);
    • PriorityBlockingQueue:优先级队列,按任务优先级执行。
(4)拒绝策略(RejectedExecutionHandler)

队列满 + 线程数达最大数时,新任务会触发拒绝策略,Java 提供 4 种默认实现:

  • AbortPolicy(默认):直接抛出RejectedExecutionException,中断程序;
  • CallerRunsPolicy:由提交任务的线程(调用者)自己执行,缓解任务压力;
  • DiscardPolicy:默默丢弃新任务,无任何提示;
  • DiscardOldestPolicy:丢弃队列中最老的任务(队首),再尝提交新任务。
5)线程工厂(ThreadFactory)
  • 用于创建线程,默认实现为Executors.defaultThreadFactory()
  • 自定义线程工厂可设置线程名称(如"order-task-thread-1")、优先级、是否守护线程等,方便问题排查。

3.Executors工具类(常用线程池)

Java 提供java.util.concurrent.Executors工厂类,快速创建常用线程池,但实际开发中不推荐直接使用(存在 OOM 风险),仅适合简单场景。

1.FixedThreadPool(固定核心线程池)

ExecutorService fixedPool = Executors.newFixedThreadPool(5);
  • 特点:核心线程数 = 最大线程数(无临时线程),队列用LinkedBlockingQueue(无界);
  • 适用:任务量稳定、需要控制并发度的场景(如接口异步处理);
  • 风险:任务堆积过多导致 OOM。

2.CachedThreadPool(缓存线程池)

ExecutorService cachedPool = Executors.newCachedThreadPool();
  • 特点:核心线程数 = 0,最大线程数 =Integer.MAX_VALUE,队列用SynchronousQueue(无缓冲),临时线程空闲 60 秒销毁;
  • 适用:短期、高频、耗时短的任务(如临时数据计算);
  • 风险:任务过多时创建大量线程,导致 OOM 或 CPU 上下文切换爆炸。

3.SingleThreadExecutor(单线程池)

ExecutorService singlePool = Executors.newSingleThreadExecutor();
  • 特点:核心线程数 = 最大线程数 = 1,队列用LinkedBlockingQueue(无界);
  • 适用:需要串行执行的任务(如日志写入、订单流水处理);
  • 风险:任务堆积导致 OOM。

4.ScheduledThreadPool(定时/周期线程池)

  • 特点:核心线程数固定,支持定时执行(schedule())或周期性执行(scheduleAtFixedRate());
  • 适用:定时任务(如每分钟刷新缓存、每天凌晨备份数据);
// 延迟2秒执行任务 scheduledPool.schedule(() -> System.out.println("延迟执行"), 2, TimeUnit.SECONDS); // 延迟1秒后,每3秒执行一次(固定频率) scheduledPool.scheduleAtFixedRate(() -> System.out.println("周期性执行"), 1, 3, TimeUnit.SECONDS);

4.线程池工作原理

  1. 提交任务时,先判断核心线程是否已满:
    • 未满:创建核心线程执行任务;
    • 已满:将任务加入阻塞队列;
  2. 若队列已满,判断当前线程数是否达到最大线程数:
    • 未达:创建临时线程执行任务;
    • 已达:触发拒绝策略;
  3. 临时线程执行完任务后,从队列取任务,空闲超过keepAliveTime则销毁;
  4. 核心线程默认不会销毁,除非设置allowCoreThreadTimeOut(true)
任务提交 → 核心线程未满?→ 核心线程执行 → 结束 ↓ 否 队列未满?→ 加入队列 → 核心线程空闲时取任务执行 → 结束 ↓ 否 线程数达最大?→ 触发拒绝策略 → 结束 ↓ 否 创建临时线程执行 → 空闲超时销毁

5.线程池状态

ThreadPoolExecutor 定义了 5 种状态(通过ctl原子变量维护,高 3 位存状态,低 29 位存线程数),状态转换不可逆:

6.任务提交方法:execute () vs submit ()

线程池提供两种提交任务的方式,核心区别在于返回值和异常处理:
1. execute()
无返回值,仅接收Runnable任务;
任务执行异常会直接抛出(需手动捕获);

executor.execute(() -> { try { // 任务逻辑 } catch (Exception e) { // 异常处理 } });

2. submit()

  • 有返回值(Future对象),可接收RunnableCallable任务;
  • 任务异常会被封装在Future中,调用future.get()时才会抛出;
// 提交Callable任务(有返回值) Future<String> future = executor.submit(() -> { return "任务执行结果"; }); // 获取结果(阻塞等待任务完成) try { String result = future.get(); // 若任务异常,此处抛出ExecutionException } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); }

7.线程池的最佳配置实践

线程池的性能依赖参数配置,需结合业务场景(CPU 密集型 / IO 密集型)优化:

1. 核心线程数(corePoolSize)

  • CPU 密集型任务(如计算、排序):核心线程数 = CPU 核心数 + 1(减少上下文切换);
    • 获取 CPU 核心数:Runtime.getRuntime().availableProcessors()
  • IO 密集型任务(如数据库查询、网络请求):核心线程数 = CPU 核心数 * 2(或 CPU 核心数 / (1 - 阻塞系数),阻塞系数通常 0.8~0.9);
    • 示例:8 核 CPU → 核心线程数 = 16。

2. 任务队列(workQueue)

  • 必须使用有界队列(如ArrayBlockingQueue),避免无界队列导致 OOM;
  • 队列容量根据业务峰值配置(如峰值任务量 = 1000 → 队列容量设为 1000~2000)。

3. 最大线程数(maximumPoolSize)

  • IO 密集型任务:最大线程数可适当增大(如核心线程数的 2 倍),应对突发流量;
  • CPU 密集型任务:最大线程数 = 核心线程数(无需临时线程,避免上下文切换)。

4. 拒绝策略(handler)

  • 核心业务(如支付、下单):用CallerRunsPolicy(调用者执行,避免任务丢失)或自定义拒绝策略(如持久化任务到 MQ / 数据库);
  • 非核心业务(如日志统计):用DiscardPolicyDiscardOldestPolicy

5. 线程工厂(threadFactory)

  • 自定义线程工厂,设置线程名称(含业务标识),方便日志排查:
    ThreadFactory threadFactory = new ThreadFactory() { private final AtomicInteger count = new AtomicInteger(1); @Override public Thread newThread(Runnable r) { Thread thread = new Thread(r); thread.setName("order-task-thread-" + count.getAndIncrement()); thread.setDaemon(false); // 非守护线程(避免主线程退出时被强制销毁) return thread; } };

    6. 关闭线程池

  • 程序退出时必须关闭线程池,否则核心线程会一直运行,导致 JVM 无法退出;
  • 两种关闭方式:
    // 1. shutdown():温和关闭,等待队列任务执行完毕,不接收新任务 executor.shutdown(); // 2. shutdownNow():强制关闭,中断正在执行的任务,返回未执行的任务 List<Runnable> unfinishedTasks = executor.shutdownNow();

8.注意事项

  • 避免使用无界队列LinkedBlockingQueue无参构造是无界队列,任务堆积会导致 OOM;
  • 线程池监控:通过ThreadPoolExecutorgetActiveCount()(活跃线程数)、getQueue().size()(队列任务数)等方法监控状态,及时调整参数;
  • 任务超时控制:用Future.get(timeout, unit)设置任务超时时间,避免线程阻塞;
  • 异常捕获execute()提交的任务必须手动捕获异常,否则线程会被销毁(核心线程会重新创建,但影响效率);
  • 禁止使用 Executors 创建线程池:阿里 Java 开发手册明确禁止,推荐自定义ThreadPoolExecutor

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1119795.shtml

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

相关文章

数据损坏类型及相关恢复方法

&#xff08;一&#xff09;文件的删除及恢复文件删除的本质是操作系统在文件目录项首位写入删除标记&#xff08;如FAT32的"0xE5"&#xff0c;NTFS的$MFT条目置空&#xff09;&#xff0c;同时在文件分配表&#xff08;FAT&#xff09;或主文件表&#xff08;MFT&am…

从175亿参数到Transformer革命:一文搞懂大语言模型的底层逻辑

一、打破认知:LLM不是魔法,是数学 当你打开ChatGPT,看着它流畅地回答问题、撰写文案、甚至编写代码时,你是否会产生一种错觉——这是某种"智能生命"? 让我先给你泼一盆冷水:大语言模型(LLM)的本质,不过是一个专门处理文本的深度神经网络。它既不是科幻电影里的人工智…

Zookeeper在大数据领域的元数据管理实践

Zookeeper在大数据领域的元数据管理实践 关键词&#xff1a;Zookeeper、大数据、元数据管理、分布式系统、实践应用 摘要&#xff1a;本文主要探讨了Zookeeper在大数据领域元数据管理方面的实践。首先介绍了相关背景知识&#xff0c;包括目的、预期读者、文档结构和术语表。接着…

企业使用智能体能省多少钱?一套可直接套用的真实ROI计算模型

在2026年企业全面进入精细化经营的背景下&#xff0c;任何技术投入都绕不开一个核心问题&#xff1a;ROI是否能在部署前算清&#xff1f;过程中能否验证&#xff1f;结果是否可复用&#xff1f;结论先行&#xff1a;企业智能体不是概念性投入&#xff0c;而是目前少数可以在上线…

高并发接口调用的线程模型与处理机制

高并发接口调用的线程模型与处理机制 一、并发调用的基本概念 当多个用户同时请求同一接口时&#xff0c;系统如何处理这些并发请求&#xff0c;核心取决于线程分配机制和资源调度策略。二、Web服务器的请求处理模型 2.1 请求线程分配机制 所有Web应用&#xff08;如Spring Boo…

基于点云和建模命令反推CADQuery代码的批量推理系统

基于点云和建模命令反推CADQuery代码的批量推理系统 1. 项目概述与设计思路 1.1 项目背景 在CAD/CAM领域,从点云数据重建CAD模型是一个具有挑战性的任务。传统方法需要复杂的几何算法和人工干预,而现代大语言模型(LLM)在理解几何关系和生成代码方面展现出强大能力。本项…

走出“实验室”走向“天空” 杭州如何托举低空经济加速起飞?

具身智能加速起跑、低空经济蓬勃发展、人工智能深入公共治理与民生服务……在新一轮科技与产业变革中&#xff0c;杭州正以制度创新、场景开放和生态协同为抓手&#xff0c;加快打通科技成果从实验室走向市场的“最后一公里”&#xff0c;全力建设具有全国影响力的人工智能创新…

0095__WiX Toolset

https://blog.csdn.net/gitblog_00552/article/details/155294915

有监督学习神经网络改造为无监督学习的PyTorch可微分优化实现

有监督学习神经网络改造为无监督学习的PyTorch可微分优化实现 1. 引言:问题背景与需求分析 1.1 原始问题描述 我们面临一个关键任务:将一个原本使用有监督学习的神经网络改造为无监督学习架构。原始模型中,标签数据是通过一个MATLAB实现的交错网格差分法函数计算得到的。…

Spring Boot测试类的使用参考

Spring Boot测试类的使用参考 1. 集成测试概述 集成测试是在完整的Spring应用上下文中测试应用组件之间的交互。与单元测试不同&#xff0c;集成测试会启动Spring容器并加载所有配置的Bean。 2. 依赖配置 2.1 Maven依赖 <!-- Spring Boot测试核心依赖 --> <dependency…

0101__WiX Toolset 安装包制作入门教程(目录篇)

https://cloud.tencent.com.cn/developer/article/2349829

高通开源驱动ath12k已正式支持QCC2072

最新消息&#xff0c;高通于25年12月底更新开源驱动ath12k&#xff0c;已正式支持QCC2072 Wi-Fi7 芯片。 驱动对应链接&#xff1a; https://git.codelinaro.org/clo/ath-firmware/ath12k-firmware/-/tree/main 补丁说明链接&#xff1a; https://lore.kernel.org/ath12k/ O…

宇信科技以金融科技前沿探索 获评《财经》新媒体2025“新奖”——“未来场景定义者”

在“十四五”与“十五五”交汇的历史节点&#xff0c;中国经济正以韧性、创新与结构性跃升为鲜明底色&#xff0c;描绘出一幅深刻转型的画卷。其中&#xff0c;以“人工智能”行动为牵引的新科技与实体经济深度融合&#xff0c;成为驱动高质量发展的核心引擎。近日&#xff0c;…

1024编程——让我们的孩子对话未来

编程到底学什么&#xff1f; 其实&#xff0c;编程思维是“理解问题——找出路径”的高效思维过程&#xff0c;它由分解、模式识别、抽象、算法四个步骤组成。编程能够培养孩子的自律性&#xff0c;需要制定规则并培养孩子形成遵守规则的意识。每一门编程语言都有自己的规则&am…

电力行业气体安全监测指南:气体检测仪的应用方案

在电力系统的日常运营与维护中&#xff0c;除了严防触电、火灾等显性风险&#xff0c;一类隐形杀手同样不容忽视——有害气体。无论是密闭变电站内的六氟化硫泄漏、电缆隧道中的缺氧与可燃气体积累&#xff0c;还是蓄电池室可能产生的氢气&#xff0c;都对设备稳定与人员安全构…

unibest+uview-plus,tabbar icon不展示

方法一&#xff1a;如果你是动态 图标的话&#xff0c;你得需要把你要显示的图标 全部先列出来&#xff0c;<template v-else-if"item.iconType unocss || item.iconType iconfont"><view :class"item.icon" class"h-20px w-20px flex ite…

学霸同款2026 AI论文工具TOP9:本科生毕业论文写作全解析

学霸同款2026 AI论文工具TOP9&#xff1a;本科生毕业论文写作全解析 2026年学术写作工具测评&#xff1a;为什么你需要这份榜单&#xff1f; 随着AI技术在学术领域的深度应用&#xff0c;越来越多的本科生开始依赖智能工具提升论文写作效率。然而&#xff0c;面对市场上琳琅满目…

vue基于spring boot的校园高校毕业生房屋租赁 预约看房 合同 报修应用和研究

文章目录研究背景与意义系统功能设计技术实现与创新应用价值与展望项目简介大数据系统开发流程主要运用技术介绍爬虫核心代码展示结论源码文档获取定制开发/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;研究背景与意义 随着高校毕业生人数逐年增加…

vue 表格 vxe-table 如何实现透视表拖拽对数据进行分组汇总,金额合计、平均值等

vue 表格 vxe-table 如何实现透视表拖拽对数据进行分组汇总&#xff0c;金额合计、平均值等,通过 custom-config.allowGroup 启用分组拖拽功能 https://vxetable.cn 拖拽列进行数据分组后自动汇总 通过拖拽列到聚合列表&#xff0c;自动对数据进行合计汇总。设置 custom-con…

语言模型在复杂系统风险评估与金融市场稳定性分析中的应用

语言模型在复杂系统风险评估与金融市场稳定性分析中的应用 关键词:语言模型、复杂系统风险评估、金融市场稳定性分析、自然语言处理、数据挖掘 摘要:本文深入探讨了语言模型在复杂系统风险评估与金融市场稳定性分析中的应用。首先介绍了研究的背景、目的、预期读者和文档结构…