栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JAVA线程池源码之深入状态值分析| Java Debug 笔记

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JAVA线程池源码之深入状态值分析| Java Debug 笔记

用原子方式更新的 int 值,底层实现用的是Unsafe的 compareAndSwapInt(乐观锁), 如果当前值 == 预期值,则以原子方式将该值设置为给定的更新值。 如果成功,则返回 true。返回 False 指示实际值与预期值不相等。

问题来了,其实它这里只是存一个Integer值而已。如何实现存二个呢?作者 Doug Lea ,采用了运算符计算的方式,来保存两个值。Integer为32位, 源码中是采用高三位保存线程状态(RUNNING,SHUTDOWN,STOP,TIDYING,TERMINATED这五个状态),三位最多可以存储7个状态。注意:但包括0,加上负数,最多就是7个状态。因为你要保障你的数都在高位,在低位的数值会被覆盖。 低29位保存当前运行的线程数量(workerCountOf),这个最大值为536870911。所以线程数受限于这个值。 我想应该也没有人设置这么大吧!嘿嘿

图片直观感受一下

对这几行代码,进行剥丝抽茧。 private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));

//高3位用来存储状态,低29位存 当前运行的线程数量

private static final int COUNT_BITS = Integer.SIZE - 3;

//这个值的大小,看自己需求吧,这个写29是给线程数留住了最大空间了.(读写锁里面这个是16, 感兴趣可以去看看ReentrantReadWriteLock.)

private static final int CAPACITY = (1 << COUNT_BITS) - 1;

//这个值很关键,就是它用来分割一个值的。CAPACITY不是随便写的,它的二进制, 都是29位的1, 1111111111111111,如果COUNT_BITS是16,代入(1 << COUNT_BITS) - 1)中, 就是低位补16个0,减一个1,结果就是16个1,如果是2,就是2个1。

线程状态值

// runState is stored in the high-order bits

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;

重点我们看看这个表格,主要前面3位。

状态二进制(32位)前3位十进制
RUNNING11100000000000000000000000000000111-536870912
SHUTDOWN000000000000000000000000000000000000
STOP00100000000000000000000000000000100536870912
TIDYING010000000000000000000000000000000101073741824
TERMINATED011000000000000000000000000000000111610612736
计算线程池状态

回顾一下前面的内容,我想应该忘得差不多了,能查到的资料,我也从来不记,我的头脑是让我思考用的。

&与运算 两个操作数中位都为1,结果才为1,否则结果为0。

~即0变成1,1变成0.(简单来说是加一,然后取反)比如 3 ,加一,是4,取反为-4.更直观的详细计算方式请看我上一章。 Thanks♪(・ω・)ノ

用RUNNING的状态来计算

//线程池状态
private static int runStateOf(int c) {
//CAPACITY =536870911,~后是-536870912
//CAPACITY 取反进制是 11100000000000000000000000000000
//RUNNING 的取进制是 11100000000000000000000000000000
//结果 进制是 11100000000000000000000000000000
//todo:结果与RUNNING相符合,敲重点,所以这里是取的高位
return c & ~CAPACITY;
}

运行的线程数量计算

我们假定目前线程运行的数量是1,线程运行状态为RUNNING。

private static int workerCountOf(int c) {
//CAPACITY 536870911 进制是 00011111111111111111111111111111
//-536870911 线程数是1 进制是 11100000000000000000000000000001
//结果 进制是 00000000000000000000000000000001
//& 两个操作数中,位都为1,结果才为1,否则结果为0
//todo:敲重点,所以这里是取的是低位。
return c & CAPACITY;
}

因为CAPACITY高位为000,所以无论怎么算(&)都是取的低29位。

更新线程池运行状态

或运算符用符号“|” ,两个位只要有一个为1,那么结果就是1,否则就为0。

private static int ctlOf(int rs, int wc) {

//比如目前状态为RUNNING,线程数量为1。那么值就是

//1110 0000 0000 0000 0000 0000 0000 0001
//0000 0000 0000 0000 0000 0000 0000 0000
//1110 0000 0000 0000 0000 0000 0000 0001 //结果
return rs | wc; }

总结

0000 0000 0000 0000 0000
//1110 0000 0000 0000 0000 0000 0000 0001 //结果
return rs | wc; }

总结
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/306277.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号