ThreadPoolExecutor 线程回收时机详解

news2025/1/21 5:48:20

个人博客

ThreadPoolExecutor 线程回收时机详解 | iwts’s blog

总集

想要完整了解下ThreadPoolExecutor?可以参考:

基于源码详解ThreadPoolExecutor实现原理 | iwts’s blog

Worker-工作线程管理

线程池设计了内部类Worker,主要是用来管理新建的线程,除了监控,核心的方法是:

  1. 执行。
  2. 申请任务。

此外还包括回收等线程监控类型方法。

由于一个工作线程对象,其中有一个具体的线程,那么本质上是不需要加锁的。竞争资源是任务队列,而任务队列由阻塞队列来实现。

可以看Worker的设计:

线程生命周期管理

线程池需要管理线程的生命周期,需要在线程长时间不运行的时候进行回收。

线程池使用一张Hash表去持有线程的引用,这样可以通过添加引用、移除引用这样的操作来控制线程的生命周期。

可以看到,workers是HashSet,那么问题来了,线程池有大量的工作线程,频繁创建/清除线程的时候,用线程不安全的HashSet必然是有并发安全问题的。

所以线程池要求在操作workers的时候,都需要获锁,根据该锁对workers进行操作:

也就是说,在工作线程的创建/销毁,都要加上这个锁,例如工作线程的创建:

工作线程的回收

这里比较复杂,慢慢聊。

工作线程自身锁

Worker对象其实本身就是一把锁。这是个细节,Worker本身是实现了AQS的:

这里其实最主要的作用是工作线程的回收。虽然可以通过维护workers来完成对工作线程生命周期的管理,新建线程比较好理解,但是删除线程的时候,工作线程本身就是一种竞争资源了。回收的时候是可能恰好碰到调用的。

这里选择AQS的原因,其实可以看注释,这边简单翻译一部分:

Worker类存在的主要意义就是为了维护线程的中断状态。因为正在执行任务的线程是不应该被中断的。在线程真正开始运行任务之前,为了抑制中断。所以把 Worker 的状态初始化为负数-1。

完全看不懂,这里从其他角度慢慢绕过来解释一下。

线程的中断与回收

解释这个问题,首先看下Worker自身是从哪里调用锁的:

  1. 工作线程处理前后加锁。
  2. 工作线程尝试中断时尝试获锁。

第一个看代码runWorker()

也就是说,当前线程如果在处理,那么本身是给自己加锁的。
第二个看代码interruptIdleWorkers()

这里是不是就有点恍然大悟的意思了。

工作线程本身实现AQS,将自身当作竞争对象。

那么工作线程工作的时候,加锁,锁住自己,那么interruptIdleWorkers()方法在执行的时候,如果能获取锁,就说明一个问题:此时当前线程是没有在工作的。那么就会被中断掉。

为了实现这个功能,就只能选择不可重入锁,所以自己实现了AQS来实现这个特性。具体可以看代码实现。

基本可以推测到,interruptIdleWorkers()这个方法就是回收方法,那么其调用时机是什么?

线程回收时机

一个重要的回收时机-keepAliveTime

这里单独拉出来聊了,比较经典。

八股文一般说:keepAliveTime是线程存活时间,如果当前线程池线程数量大于核心池的时候,如果一个线程超过keepAliveTime没有获取到任务,则会触发线程回收。

这里聊聊相关源码。首先看基础的任务申请:

这里如果设置了超时时间的情况下,请求任务队列是调用的poll()方法,并指定了keepAliveTime。那么这个方法的意思就是,阻塞这么长时间,超过时间后直接返回null。

所以这里就对应到八股文了,如果此时poll()返回空,那么就是说当前队列里什么数据都没有,那么这里其实就是说明:该线程等待了keepAliveTime都没有获取到数据,也就是说这段时间全部是空闲。可以回收了。

而这里只是设置了timedOut标记,留给上层来处理:

这里判定之后返回个null。

直接跳出线程执行run()方法,在finally块中触发线程回收。processWorderExit()方法的底层就是下面的tryTerminate()了,会直接进行回收。

tryTerminate()

核心回收方法,根据其调用可以梳理出正常运行中的回收时机:

  1. 工作线程创建失败时:addWorkerFailed()

  2. runWorker()方法退出时。正常来说runWorker()方法是一个自旋,只有在任务申请失败时才会退出自旋。那么这个时机就是指任务队列已经清空了:

    总体流程为:

  3. shutdown()。可以看到执行了两次。

  4. shutdownNow()。

  5. remove(),移除任务时顺便执行一次。

  6. purge(),todo。

interruptIdleWorkers

一般是针对线程池本身参数进行操作的时候,会触发回收,看其调用方式,可以梳理出来全部的线程回收时机:

  1. shutdown()。
  2. 设置核心池大小的时候,如果当前线程池线程数量大于核心池数量大小,执行一次回收:
  3. 设置允许核心池超时时,执行一次回收:
  4. 设置最大池数量时,如果当前线程池线程数量大于最大池数量,执行一次回收:
  5. 设置线程池线程存活时间时,如果设置变小了,那么执行一次回收:

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

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

相关文章

AI agent是什么,什么技术栈

AI agent,也称为会话代理或聊天机器人, 是一种通过文本或语音模拟人类对话的计算机程序。 它们旨在以自然且引人入胜的方式理解和响应用户输入。 AI agent 被广泛用于各种应用中,包括客户服务、营销、 销售和教育。 有两种主要类型的 AI agen…

2.linux操作系统CPU使用率和平均负载区别

目录 概述cpu使用率区别 结束 概述 linux操作系统CPU 使用率 和 平均负载 区别 负载高并不一定使用率高,有可能 cpu 被占用,但不干活。 cpu使用率 cpu使用率:cpu非空闲态运行的时间占比,反映cpu的繁忙程度,和平均负载…

DS18B20单总线数字温度传感器国产替代MY18E20 MY1820 MY18B20Z MY18B20L(一)

前言 DS18B20是全球第一个单总线数字温度传感器,推出时间已经超过30年,最早由美国达拉斯半导体公司推出,2001年1月,美信以25亿美元收购达拉斯半导体(Dallas Semiconductor),而美信在2021年8月被…

使用vscode+git+github管理代码

一、打开代码所在的文件夹 以我最近的看的一个代码项目为例 打开如下 为了方便日后打开,可以把经常看的代码拉出来,然后建一个工作区,后续查看也方方便。直接点开下面第二张图的工作区文件就可以。 二、将代码上传到github 会自动创建一个同名…

成为画图大师,用图表讲故事

这些问题你是否遇到过: 项目总结会上,如果用数据呈现你做的价值? 完善详尽的数据分析得出了让人信服的结论,如何呈现在BOSS面前? 我们要的不是数据,而是数据告诉我们的事实 数据很重要,但只是原料,所以…

分治精炼宝库-----快速排序运用(⌯꒪꒫꒪)੭

目录 一.基本概念: 一.颜色分类: 二.排序数组: 三.数组中的第k个最大元素: 解法一:快速选择算法 解法二:简单粗暴优先级队列 四.库存管理Ⅲ: 解法一:快速选择 解法二:简单粗…

Tcmalloc工具定位内存泄漏问题

内存泄漏问题定位 gperftools工具安装 执行如下操作: git clone https://github.com/gperftools/gperftools.git 注:如果网速较慢,可直接去下载压缩包。 如我下载的地址:https://github.com/gperftools/gperftools/releases/ta…

Unity动画系统(1)

6.1 动画系统基础1-5_哔哩哔哩_bilibili 模型信息 Generic非人型 Configure 虚线圈可以没有,实线圈必须有,15个骨骼是必须的 p313 尾巴、翅膀属于非人型 p314 一般使用create from this model 游戏对象不再旋转 游戏对象不再发生位移 调整中心位置

八月份的护网行动如何参加?

护网行动背景 什么是“护网行动”? 指挥机构∶由公安机关统一组织的"网络安全实战攻防演习"。 护网分为两级演习∶公安部对总部,省厅对省级公司。 什么是“实战攻防演习” 每支队伍3-5 人组成,明确目标系统,不限制攻…

Class Constructors and Destructors (类的构造函数和析构函数)

Class Constructors and Destructors [类的构造函数和析构函数] 1. Declaring and Defining Constructors (声明和定义构造函数)2. Using Constructors (使用构造函数)3. Default Constructors (默认构造函数)4. Destructors (析构函数)5. Improving the Stock Class (改进 Sto…

使用 privacyIDEA 实现 Windows RDP 多因素认证 (MFA)

前言 在等保 2.0 标准中有要求: d)应采用口令、密码技术、生物技术等两种或两种以上组合的鉴别技术对用户进行身份鉴别,且其中一种鉴别技术至少应使用密码技术来实现。 可以借助开源的 privacyIDEA 配合 AD 域环境实现 RDP MFA 认证登录以满足上面的要…

docker安装rocketMq5x以上的版本

1.背景 安装RocketMQ 5.x以上的版本主要是因为新版本引入了许多性能优化、新功能以及对已有特性的增强,这些改进可以帮助提升消息队列系统的稳定性和效率。 1.性能提升:RocketMQ 5.x版本通常包括了对消息处理速度、吞吐量和延迟的优化,使得系…

大模型压缩-LoRAP

这里写目录标题 1.多头注意力和FFN的权重分布2 多头矩阵的低秩分解FFN无梯度通道剪枝 这篇文章 1期望找到一个“剪枝+低秩分解”的路子,使结构化剪枝达到非结构化剪枝的性能。 1.多头注意力和FFN的权重分布 Fig. 1.1 多头注意力权重矩阵 从Fig.1.1可以看…

万字浅析视频搜索系统中的多模态能力建设

万字浅析视频搜索系统中的多模态能力建设 FesianXu 20240331 at Tencent WeChat search team 前言 视频搜索是天然的富媒体检索场景,视觉信息占据了视频的一大部分信息量,在视频搜索系统中引入多模态能力,对于提高整个系统的能力天花板至关重…

学习感悟丨在誉天学习数通HCIP怎么样

大家好,我是誉天学员的徐同学,学习的数通HCIP课程。 在学校的时候,听说下半年就要出去实习了,心中坎坷不安,现在我学到的知识远远不够的。然后就想着学点东西充实一下自己的知识面和专业能力,有一次和同学谈…

【STM32嵌入式系统设计与开发---传感器拓展】——1_4_标准库FreeRTOS移植实验

目录 雅俗理解源码下载链接知识拓展步骤1:stm32f103vet6移植freeRTOS步骤:(1)准备开发环境(2)添加FreeRTOS移植 致谢 雅俗理解 雅:FreeRTOS是一个开源的实时操作系统(RTOS)&#xf…

数字图像处理之【高斯金字塔】与【拉普拉斯金字塔】

数字图像处理之【高斯金字塔】与【拉普拉斯金字塔】 1.1 什么是高斯金字塔? 高斯金字塔(Gaussian Pyramid)是一种多分辨率图像表示方法,用于图像处理和计算机视觉领域。它通过对原始图像进行一系列的高斯平滑和下采样操作&#x…

【例子】webpack 开发一个可以加载 markdown 文件的加载器 loader 案例

Loader 作为 Webpack 的核心机制,内部的工作原理却非常简单。接下来我们一起来开发一个自己的 Loader,通过这个开发过程再来深入了解 Loader 的工作原理。 这里我的需求是开发一个可以加载 markdown 文件的加载器,以便可以在代码中直接导入 m…

Pikachu靶场--Sql Inject

参考借鉴 pikachu靶场练习(详细,完整,适合新手阅读)-CSDN博客 数字型注入(post) 这种类型的SQL注入利用在用户输入处插入数值,而不是字符串。攻击者试图通过输入数字来修改SQL查询的逻辑,以执行恶意操作。…

前端笔记-day11

文章目录 01-空间-平移02-视距03-空间旋转Z轴04-空间旋转X轴05-空间旋转Y轴06-立体呈现07-案例-3D导航08-空间缩放10-动画实现步骤11-animation复合属性12-animation拆分写法13-案例-走马灯14-案例-精灵动画15-多组动画16-全民出游全民出游.htmlindex.css 01-空间-平移 <!D…