线程池(ThreadPoolExecutor)实现原理和源码细节是Java高并发面试和实战开发的重点


一、线程池核心流程图

+-----------------+
|    提交任务      | submit/execute
+-----------------+|v
+-----------------+
| 判断核心线程数  | < corePoolSize?
+-----------------+|Yes        |Nov           v
[创建新线程]   +-----------------+| 队列是否满?     |+-----------------+|No        |Yesv           v[入队列排队]   +------------------+| 判断最大线程数  |+------------------+|No          |Yesv             v[创建新线程]   [执行拒绝策略]

二、线程池主要环节及源码方法

1. 任务提交(execute/submit)

方法:

  • execute(Runnable command)
  • submit(Runnable/Callable)

源码片段:

public void execute(Runnable command) {if (command == null)throw new NullPointerException();int c = ctl.get();if (workerCountOf(c) < corePoolSize) {if (addWorker(command, true))return;c = ctl.get();}if (isRunning(c) && workQueue.offer(command)) {int recheck = ctl.get();if (!isRunning(recheck) && remove(command))reject(command);else if (workerCountOf(recheck) == 0)addWorker(null, false);}else if (!addWorker(command, false))reject(command);
}

注释速记:

  • 任务先尝试用核心线程处理。
  • 核心线程满则尝试入队列。
  • 队列满则尝试新建非核心线程。
  • 实在不行,执行拒绝策略。

口诀:
先核心,后队列;队列满,再扩容;全满员,拒绝它。


2. 核心线程判断与创建

方法:

  • addWorker(Runnable firstTask, boolean core)

源码片段:

private boolean addWorker(Runnable firstTask, boolean core) {retry:for (;;) {int c = ctl.get();int rs = runStateOf(c);// ...省略状态判断for (;;) {int wc = workerCountOf(c);if (wc >= CAPACITY ||wc >= (core ? corePoolSize : maximumPoolSize))return false;if (compareAndIncrementWorkerCount(c))break retry;c = ctl.get();if (runStateOf(c) != rs)continue retry;}}// ...真正创建Worker线程
}

注释速记:

  • 根据core参数决定是否用核心线程池大小。
  • 用CAS增加线程计数,线程安全。

口诀:
核心先上,CAS抢位,线程安全,才创建。


3. 入队列

方法:

  • workQueue.offer(command)

源码片段:

if (isRunning(c) && workQueue.offer(command)) {// 入队成功后可能需要唤醒线程
}

注释速记:

  • 队列没满则入队。
  • 入队后如果线程都在忙,线程池不会立刻扩容。

口诀:
队列能放,直接排队。


4. 非核心线程扩容

逻辑:

  • 当核心线程和队列都满时,允许创建新线程(最大线程数以内)。

源码片段:

else if (!addWorker(command, false))reject(command);

注释速记:

  • 只有在核心线程和队列都满时才会扩容到最大线程数。

口诀:
满员排队,再扩容。


5. 拒绝策略

方法:

  • RejectedExecutionHandler.rejectedExecution(Runnable r, ThreadPoolExecutor e)

源码片段:

public static class AbortPolicy implements RejectedExecutionHandler {public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {throw new RejectedExecutionException();}
}

注释速记:

  • 线程池和队列都满时,根据策略处理(抛异常/丢弃/调用者执行等)。

口诀:
全都满员,策略管。


6. 线程回收与销毁

方法:

  • worker.run()
  • 判断空闲时间超过keepAliveTime

源码片段:

while (task != null || (task = getTask()) != null) {// 执行任务
}

注释速记:

  • 非核心线程空闲时间到达后会被回收。
  • 核心线程默认不会被回收(可通过allowCoreThreadTimeOut配置)。

口诀:
闲太久,自动走。


三、流程口诀速记

提任务,先核心,队列排,扩满员;全满员,策略管;空闲久,自动走。


四、常用方法与内部逻辑简表

阶段关键方法/类主要逻辑说明
任务提交execute/submit任务进线程池
核心线程判断addWorker(core=true)核心线程是否有空位,有则新建
入队列workQueue.offer核心线程满,队列没满则排队
非核心线程addWorker(core=false)队列满,是否可新建非核心线程
拒绝策略RejectedExecutionHandler全部满员,执行拒绝策略
线程回收allowCoreThreadTimeOut非核心线程闲置超时自动销毁

五、源码脉络图(伪代码)

execute(command) {if (核心线程未满)addWorker(command, true)  // 新核心线程else if (队列未满)workQueue.offer(command)  // 入队列else if (线程池未满)addWorker(command, false) // 新非核心线程elsereject(command)           // 拒绝策略
}

六、速记口诀总结

场景口诀
任务进池先核心,后队列
队列满了再扩容(到最大线程数)
全满员策略管(拒绝策略)
线程回收闲太久,自动走
全流程提任务,先核心,队列排,扩满员;全满员,策略管;空闲久,自动走。

七、配图(流程图)

         +-------------------------+|      提交任务           |+-------------------------+|+-------------+-------------+|                           |
+-----v-----+               +-----v-----+
| 核心线程? |----是-------->| 创建线程  |
+-----------+               +-----------+|否|
+-----v-----+
| 队列满?   |----否-------> 入队列
+-----------+|是|
+-----v-----+
| 最大线程? |----否-------> 创建线程
+-----------+|是|
+-----v-----+
| 拒绝策略  |
+-----------+

八、结语

通过以上细化,线程池的工作原理、源码关键点、方法流程、口诀速记都一目了然。
只要记住口诀和流程图,结合源码细节,面试和实战都能轻松拿捏!

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

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

相关文章

学习海康VisionMaster之直方图工具

一&#xff1a;进一步学习了 今天学习下VisionMaster中的直方图工具&#xff1a;就是统计在ROI范围内进行灰度级分布的统计 二&#xff1a;开始学习 1&#xff1a;什么是直方图工具&#xff1f; 直方图工具针对输入灰度图像的指定ROI区域&#xff0c;输出该区域的图像灰度直方…

计算机网络 : Socket编程

计算机网络 &#xff1a; Socket编程 目录 计算机网络 &#xff1a; Socket编程引言1.UDP网络编程1.1 网络地址与端口转换函数1.2 本地环回1.3 EchoServer1.4 DictServer1.5 DictServer封装版1.6 简单聊天室 2.TCP网络编程2.1 TCP Socket API详解2.2 Echo Server2.3 Echo Serve…

Elasticsearch/OpenSearch 中doc_values的作用

目录 1. 核心作用 2. 适用场景 3. 与 index 参数的对比 4. 典型配置示例 场景 1&#xff1a;仅用于聚合&#xff0c;禁止搜索 场景 2&#xff1a;优化大字段存储 5. 性能调优建议 6. 底层原理 doc_values 是 Elasticsearch/OpenSearch 中用于优化查询和聚合的列式存储结…

使用mermaid 语言绘画时序图和链路图

给大家展示一下效果&#xff0c; 官方地址&#xff1a;https://mermaid.nodejs.cn/ 官方开发地&#xff1a;https://mermaid.nodejs.cn/intro/#google_vignette graph LR%% 样式定义&#xff08;完全保留&#xff09; classDef user fill:#E1F5FE,stroke:#0288D1;classDef …

C++ Kafka客户端(cppkafka)安装与问题解决指南

一、cppkafka简介 cppkafka是一个现代C的Apache Kafka客户端库&#xff0c;它是对librdkafka的高级封装&#xff0c;旨在简化使用librdkafka的过程&#xff0c;同时保持最小的性能开销。 #mermaid-svg-qDUFSYLBf8cKkvdw {font-family:"trebuchet ms",verdana,arial,…

STM32的ADC模块中,**采样时机(Sampling Time)**和**转换时机(Conversion Time),获取数据的时机详解

在STM32的ADC模块中&#xff0c;**采样时机&#xff08;Sampling Time&#xff09;和转换时机&#xff08;Conversion Time&#xff09;**是ADC工作流程中的两个关键阶段&#xff0c;直接影响采样精度和系统实时性。以下是详细解析&#xff1a; 1. 采样时机&#xff08;Samplin…

Pageassist安装(ollama+deepseek-r1)

page-assist网站&#xff1a;https://github.com/n4ze3m/page-assist 首先电脑配置node.js&#xff0c;管理员打开命令窗口输入下面命令下载bun npm install -g buncd 到你想要安装page-assist的地方&#xff08;推荐桌面&#xff09; 输入下列命令 git clone https://gith…

APC 荧光通道专用!Elabscience® CD11b 抗体激发 / 发射光谱精准匹配流式检测

内容概要 Elabscience APC Anti-Mouse/Human CD11b Antibody [M1/70]&#xff08;货号&#xff1a;E-AB-F1081E&#xff09;是一款高特异性荧光标记抗体&#xff0c;适用于流式细胞术&#xff08;FCM&#xff09;&#xff0c;可精准检测小鼠和人类样本中的 CD11b 髓系细胞&…

entity线段材质设置

在cesium中,我们可以改变其entity线段材质,这里以直线为例. 首先我们先创建一条直线 const redLine viewer.entities.add({polyline: {positions: Cesium.Cartesian3.fromDegreesArray([-75,35,-125,35,]),width: 5,material:material, 保存后可看到在地图上创建了一条线段…

大模型数据分析破局之路20250512

大模型数据分析破局之路 本文面向 AI 初学者、数据分析从业者与企业技术负责人&#xff0c;围绕大模型如何为数据分析带来范式转变展开&#xff0c;从传统数据分析困境谈起&#xff0c;延伸到 LLM MCP 的协同突破&#xff0c;最终落脚在企业实践建议。 &#x1f30d; 开篇导语…

【MySQL】索引太多会怎样?

在 MySQL 中&#xff0c;虽然索引可以显著提高查询效率&#xff0c;但过多的索引&#xff08;如超过 5-6 个&#xff09;会带来以下弊端&#xff1a; 1. 存储空间占用增加 每个索引都需要额外的磁盘空间存储索引树&#xff08;BTree&#xff09;。对于大表来说&#xff0c;多个…

使用PocketFlowSharp创建一个Human_Evaluation示例

效果 实践 有时候AI生成的结果我们并不满意在进入下一步之前&#xff0c;我们需要对AI生成的结果进行人工审核&#xff0c;同意了才能进入下一个流程。 Human_Evaluation就是人工判断的一个简单示例。 internal class Program{static async Task Main(string[] args){// Load…

【项目】自主实现HTTP服务器:从Socket到CGI全流程解析

00 引言 ​ 在构建高效、可扩展的网络应用时&#xff0c;理解HTTP服务器的底层原理是一项必不可少的技能。现代浏览器与移动应用大量依赖HTTP协议完成前后端通信&#xff0c;而这一过程的背后&#xff0c;是由网络套接字驱动的请求解析、响应构建、数据传输等一系列机制所支撑…

SQL练习(6/81)

目录 1.寻找连续值 方法一&#xff1a;使用自连接&#xff08;Self-Join&#xff09; 方法二&#xff1a;使用窗口函数&#xff08;Window Functions&#xff09; 2.寻找有重复的值 GROUP BY子句 HAVING子句 常用聚合函数&#xff1a; 3.找不存在某属性的值 not in no…

【流程控制结构】

流程控制结构 流程控制结构1、顺序结构2、选择结构if基本选择结构if else语法多重if语法嵌套if语法switch选择结构 3、循环结构循环结构while循环结构程序调试for循环跳转语句区别 流程控制结构 1、顺序结构 流程图 优先级 2、选择结构 if基本选择结构 单if 语法 if&…

【机器人】复现 UniGoal 具身导航 | 通用零样本目标导航 CVPR 2025

UniGoal的提出了一个通用的零样本目标导航框架&#xff0c;能够统一处理多种类型的导航任务。 支持 对象类别导航、实例图像目标导航和文本目标导航&#xff0c;而无需针对特定任务进行训练或微调。 本文分享UniGoal复现和模型推理的过程&#xff5e; 查找沙发&#xff0c;模…

python + flask 做一个图床

1. 起因&#xff0c; 目的: 对这个网站&#xff1a;https://img.vdoerig.com/ &#xff0c; 我也想实现这种效果。做一个简单的图床&#xff0c;后面&#xff0c;可以结合到其他项目中。 2. 先看效果 实际效果。 3. 过程: Grok 聊天&#xff1a; https://img.vdoerig.co…

Java生产环境设限参数教学

哈哈&#xff0c;这个问题问得好&#xff01;咱们用开餐厅的比喻来理解生产环境的四大必须设限参数&#xff0c;保证你听完再也不会忘&#xff01;&#xff08;搓手手&#xff09; 1. 堆内存上限&#xff1a;-Xmx&#xff08;厨房的最大容量&#xff09; 问题&#xff1a;想象…

电脑出故障驱动装不上?试试驱动人生的远程服务支持

在日常工作或学习中&#xff0c;驱动问题时常成为电脑用户的一大困扰。尤其是在更换硬件、重装系统、驱动冲突等情况下&#xff0c;许多用户往往手足无措&#xff0c;不知道从何下手。而“驱动人生”作为国内领先的驱动管理工具&#xff0c;一直以高效、便捷、智能著称。现在&a…

JS手写代码篇---手写 instanceof 方法

2、手写 instanceof 方法 instancecof用于检测一个对象是否是某个构造函数的实例。它通常用于检查对象的类型&#xff0c;尤其是在处理继承关系时。 eg: const arr [1,2,3,4,5]console.log(arr instanceof Array); // trueconsole.log(arr instanceof Object); // true那这是…