美文网首页
java源码系列-线程池ThreadPoolExecutor中的

java源码系列-线程池ThreadPoolExecutor中的

作者: yinkaihua | 来源:发表于2017-03-06 22:22 被阅读0次

    1、变量定义

    ThreadPoolExecutor中有一个重要的变量ctl,定义如下:

    图1

    看注释可以知道,这个变量有两个作用:

    1、记录有效的线程数量,即 workerCount

    2、记录当线程池的状态,即 runState

    2、原理分析

    这个变量是如何同时记录这两个值的呢?答案是:位运算。下面详细说明一下

    首先说线程池的状态,根据代码可以知道,线程池的状态有5种:RUNNING,SHUTDOWN,STOP,TIDYING,TERMINATED。如果用二进制表示的话,这5种状态至少需要3位来表示,而一个 int 类型的数占32位,所以,高3位表示线程状态(runState),剩下的29位表示线程数量(workerCount)。线程数量最大值为 00011111 11111111 11111111 11111111,即 2^29 - 1。

    为什么要低29位来保存 workerCount,因为线程状态这个数据只关心能否表示5个值,并不关心具体数值,而 workerCount 是需要计算具体数据的,所以低29位可以直接拿来用,并不需要额外的运算(注:如果用高29位表示 workerCount,还需要进行右移操作才能取得真正的数值)。

    3、相关方法

    主要分析一下与 ctl 相关的方法和变量。

    图2

    COUNT_BITS:等于29。即 workerCount 所占的位数。

    CAPACITY:1左移29位减1=2^29-1,workerCount 的最大值。单词意思为容量,很形象。

    下面是5种状态:-1、0、1、2、3分别左移29位,占据高3位。可以看到,源码中是用11100000,00000000,00100000,01000000,01100000来表示5种状态的。(注:应该是32位,为了省事没有全写出来,剩下的24位全部为0)

    把两个数值存在同一个变量的原理已经了解了,那么当需要分别读取 runState 和 workerCount 时,又要怎么获取各自的数值呢?图3的代码给出了答案

    图3

    主要通过 &(按位与)操作符来实现两个数据的拆分。若要获取高3位,&11100000 00000000 00000000 00000000,可以保留高3位,把低29位全部变为0,再与上边定义的常量进行比较即可。若要获取低29位,&00011111 11111111 11111111 11111111,可以把高3位变为0,低29位保留。

    至于两个数据的组装,则是通过 |(按位或)运算符实现的,大家可以自己尝试分析一下。

    相关文章

      网友评论

          本文标题:java源码系列-线程池ThreadPoolExecutor中的

          本文链接:https://www.haomeiwen.com/subject/dvqugttx.html