线程池:ThreadPoolExcutor源码阅读()

  本篇文章为你整理了线程池:ThreadPoolExcutor源码阅读()的详细内容,包含有 线程池: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 29 = 11100000 00000000 00000000 (左移29位, 移动多少位, 后面补多少个0, 高于32位的去掉)。

  各个state:

  -1 29 = 11100000 00000000 00000000 = RUNNINGZ

  0 29 = 00000000 00000000 00000000 = SHUTDOWN

  1 29 =00100000 00000000 00000000 = STOP

  2 29 =01000000 00000000 00000000 = TIDYING

  3 29 =01100000 00000000 00000000 = TERMINATED

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

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

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

  

  再看CAPACITY = (1 29) -1:

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

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

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

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

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

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

  

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

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

  11100000 00000000 00000000 00000000 00000000 00000000 = 11100000 00000000 00000000

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

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

  

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

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

  CAPACITY = (1 29)- 1 = 00100000 00000000 00000000 - 1 = 00011111 11111111 11111111

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

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

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

  c ~CAPACITY =00100000 00000000 00000011 11100000 00000000 00000000 = 00100000 00000000 00000000,

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

  

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

  

  以上就是线程池:ThreadPoolExcutor源码阅读()的详细内容,想要了解更多 线程池:ThreadPoolExcutor源码阅读的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: