线程池:ThreadPoolExcutor源码阅读

ThreadPoolExcutor源码流程图:(图片较大,下载再看比较方便)

线程池:ThreadPoolExcutor源码阅读

线程池里的二进制奥秘

前言:

线程池的五种状态state (RUNNING 、SHUTDOWN 、STOP 、TIDYING 、TERMINATED )和线程池的工作线程数:workerCount,

这两个变量,可有通过一个变量ctl 转成二进制后而获得。

直接看线程池ThreadPoolExecutor 源码里,管理状态和工作线程数的代码

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

private static final int RUNNING    = -1 << COUNT_BITS;
private static final int SHUTDOWN   =  0 << COUNT_BITS;
private static final int STOP       =  1 << COUNT_BITS;
private static final int TIDYING    =  2 << COUNT_BITS;
private static final int TERMINATED =  3 << COUNT_BITS;

private static int runStateOf(int c)     { return c & ~CAPACITY; }
private static int workerCountOf(int c)  { return c & CAPACITY; }
private static int ctlOf(int rs, int wc) { return rs | wc; }

Integer.size 为Integer 类型最大值的二进制的位数:32 (位),COUNT_BITS = 29 (位),为啥是要要减去3 ,拿个29 呢,因为它想用二进制高3 位来表示线程池的状态(state ),后面的29 位用来表示工作线程数量(workerCount )。

比如RUNNINGZ 状态是-1 左移29 位,即:

-1 的二进制算法,先取绝对值1 的二进制:00000000 00000000 00000001 ,再取反码:11111111 11111111 11111110

再取补码(加1 ):11111111 11111111 11111111 ,这就是-1 的二进制表示。

左移运算:-1<

各个state :

-1<

0<< 29 =000 00000 00000000 00000000 => SHUTDOWN

1 <

2 <

3 <

线程池就是这样用高三位来表示不同的状态。

所以状态还有这样的关系: RUNNINGZ < SHUTDOWN < STOP < TIDYING < TERMINATED

不管各个状态低29 位是啥,这个关系都不会变。

再看CAPACITY = (1<

即00100000 00000000 00000000 – 1 = 00011111 11111111 11111111 ,这是线程池最大容量线程数(536870911 ),

即是用1 到29 位可表示线程的数量,那么,ctl = state.高3 位+低29 位,如:

ctl =111 11111 11111111 11111111 ,表示线程池是RUNNINGZ 状态,且线程数为536870911 ;

ctl =000 00000 00000000 00000001 ,表示线程池是SHUTDOWN 状态,且线程数为1 ;

CAPACITY=536870911 ,表示线程池最大线程数容量为536870911 ,但这个最大数值可以忽略,

因为在实例化线程池的时候,已经通过传参数设置了核心线程数、允许最大线程数。

初始化为 ctl = new AtomicInteger(ctlOf (RUNNING, 0));

ctlOf (RUNNING, 0)参数中的0 ,意思是初始化线程池的线程数为0 。然后通过ctlOf做或运算,即:

111 00000 00000000 00000000 | 00000000 00000000 00000000 =111 00000 00000000 00000000

运算后的结果,把表示状态的高3 位、表示线程数的低29 位组合起来得到一个数ctl ,

下次拿到ctl 之后,就知道此时线程池的状态和线程数量了。

1、那么runStateOf(int c)方法具体是怎么知道线程池的状态的?

假设c = ctl.get() =001 00000 00000000 00000011 ,表示STOP 状态且还有3 个线程

CAPACITY =(1<

为啥要减1 呢?因为减1 后:

1 、把表示状态的高3 位给挪留出来了,值又可以表示线程池最大线程数。

2 、把表示线程数的低29 位变为了1 ,那~CAPACITY = 11100000 00000000 00000000 , 所以:

c &~CAPACITY =001 00000 00000000 00000011 & 11100000 00000000 00000000 =001 00000 00000000 00000000 ,

结果001 00000 00000000 00000000 保持c 的高3 位不变,把c 的低29 位全变成0,这就是获得线程池是STOP 状态

2、通过workerCountOf(int c)获取工作线程数,同上理

Original: https://www.cnblogs.com/incognitor/p/16401160.html
Author: 無名之徒
Title: 线程池:ThreadPoolExcutor源码阅读

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/622645/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 一段文字

    https://book.douban.com/review/13674387/现代人的困境,其实从出生开始每个人都有强烈的感受。我们会按户口管理,强调身份的是各种标签,各种统计数…

    数据库 2023年6月11日
    077
  • [MySQL]MySQL8.0的一些注意事项以及解决方案

    1. MySQL8.0 修改大小写敏感配置 天坑MySQL8.0! 在安装后, 便无法通过修改配置文件,重启服务,或者执行sql来更改数据库配置, 要想配置的话, 必须在MySQL…

    数据库 2023年5月24日
    075
  • iperf3的使用

    工具/原料 windows系统,iperf 32位和64位; 客户端和服务端的bat文件 方法/步骤 进入文件夹下面,运行”服务端iperf.bat”文件 …

    数据库 2023年6月9日
    075
  • Java学习-第一部分-第一阶段-第八节:项目-房屋出租系统

    项目-房屋出租系统 笔记目录:(https://www.cnblogs.com/wenjie2000/p/16378441.html) 房屋出租系统-需求 ●项目需求说明 实现基于…

    数据库 2023年6月11日
    073
  • Java面试题(二)–MySQL

    1 存储引擎 1、简单描述一个Mysql的内部结构? MySQL的基本架构示意图:大体来说,MySQL可以分为 server层和 存储引擎层两部分。 ① server层包括连接器、…

    数据库 2023年6月16日
    084
  • 猴子吃桃(递归)

    递归案例实践分析 猴子偷桃 题目描述: 猴子第一天摘下若干桃子,当即吃了一半,觉得好吃不过瘾,于是又多吃了一个,,第二天又吃了前天剩余桃子数量的一半,觉得好不过瘾,于是又多吃了一个…

    数据库 2023年6月16日
    0158
  • docker部署mysql集群

    docker部署mysql集群 1.0 安装环境 1.1 安装Centos7 Docker官方建议在Ubuntu中安装,因为Docker是基于Ubuntu发布的,而且一般Docke…

    数据库 2023年6月9日
    093
  • 细数线程池五大坑,一不小心线上就崩了

    系统性能优化的几种常用手段是异步和缓存。因此我们常常使用线程池异步处理一些业务。 线程池的使用还是相对比较简单的,首先创建一个线程池,然后通过execute或submit执行任务。…

    数据库 2023年6月6日
    0146
  • 2021年想做的最后挣扎

    一年的时间转眼间就过完,感觉没变,又感觉跟一年前的今天变化还是蛮多的,树立个小目标争取年前完成把 读书一本书看一篇文章: 《百年孤独》:我总感觉虽然是只单身狗是孤单的,理解不了孤独…

    数据库 2023年6月6日
    075
  • mysql的安装和下载

    1、 MySQL 下载地址为: MySQL 下载,这里下载的是mysql的msi安装文件,选择下面的470.2M的版本,点击download进行下载。 2、在下载页面直接选择: N…

    数据库 2023年5月24日
    090
  • 5 float f = 3.4,是否正确

    不正确,赋值运算符 “=” 左右两边的精度类型不匹配。 Java中,有小数点的默认被存储为double类型,即双精度;而float类型的变量为单精度。 可以…

    数据库 2023年6月6日
    076
  • mysql拆分字符串做条件查询

    mysql拆分字符串作为查询条件 有个群友问一个问题 这表的ancestors列存放的是所有的祖先节点,以 ,分隔 例如我查询dept_id为103的所有祖先节点,现在我只有一个d…

    数据库 2023年6月16日
    065
  • Java学习-第一部分-第一阶段-第六节:面向对象编程(基础)

    面向对象编程(基础) 笔记目录:(https://www.cnblogs.com/wenjie2000/p/16378441.html) 类与对象 ●使用现有技术解决 张老太养了两…

    数据库 2023年6月11日
    0122
  • MySQL–排序检索数据(ORDER BY)

    检索出的数据并不是以纯粹的随机顺序显示的。如果不排序,数据一般将以它在底层表中出现的顺序显示。这可以是数据最初添加到表中的顺序。但是,如果数据后来进行过更新或删除,则此顺序将会受到…

    数据库 2023年6月16日
    079
  • Python–软件目录结构

    目的不必多说:提高项目可读性、可维护性 软件目录结构示例: 那么问题来了,当类似于如上的目录结构时,我怎么在game.py中去调用setting.py或者main.py中的函数呢?…

    数据库 2023年6月9日
    083
  • 对于Java循环中的For和For-each,哪个更快

    Which is Faster For Loop or For-each in Java 对于Java循环中的For和For-each,哪个更快 通过本文,您可以了解一些集合遍历技…

    数据库 2023年6月11日
    088
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球