美文网首页JUC并发包
ThreadPoolExecutor源码历险-位运算技巧

ThreadPoolExecutor源码历险-位运算技巧

作者: 于情于你 | 来源:发表于2021-01-12 19:26 被阅读0次

    我体会到的ThreadPoolExcutor的源码阅读可分为几部分

    1.ThreadPoolExcutor构造函数(上一篇简书里面已经写过了)
    2.位运算技巧
    3.不可变内部类Worker
    4.主流程常用方法
    5.拒绝策略静态内部类
    6.工作队列类型

    构造函数就不多说了,请参考jdk源码或者移步上一篇

    重要属性及位运算技巧

    要说ThreadPoolExcutor里面的位运算技巧,首先要了解核心原子属性ctl

        private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
    

    ctl是主要的池状态控制变量,是一个包装了两个概念字段的原子整数。
         1.workerCount 有效线程数
         2.runState 运行状态,运行、关闭等。
    ctlOf的实现:

        private static int ctlOf(int rs, int wc) { return rs | wc; }
    

    也就是拿运行状态(rs),和有效线程数(wc)做位运算,位运算的意义是把这两个属性给整合到一块,比如:

    STOP       001,00000000000000000000000000000
    WorkCount:000,00000000000000000000000000001
    ctl的最终值:001,00000000000000000000000000001

        这里注意在ThreadPoolExcutor里面,状态有5种,并且只占最高位3位(左移了29位),剩下的低29位是给工作线程数量(wc)留的。
        状态占用3位的原因是状态有5种,表示5种状态最少要用3位。

        private static final int COUNT_BITS = Integer.SIZE - 3;
    
        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;
    

    5种状态的解释:

    RUNNING:接受新任务,并且可以处理任务队列中的任务
    SHUTDOWN:不接受新任务,但是会处理队列中的剩余任务
    STOP:不接受新任务,不处理排队任务以及中断进行中的任务
    TIDYING:所有任务都已终止,workerCount为零,转换为状态TIDYING的线程将运行终止的hook方法terminated()

    TERMINATED:terminated()方法执行完毕

    这里有两个重要的方法runStateOf、workerCountOf要说一下,上面说过ThreadPoolExcutor里面状态会占用ctl的高三位,所以剩下的29位是用来表示线程数量的。

        // 线程数最大限制
        private static final int CAPACITY   = (1 << COUNT_BITS) - 1;
    
        // 获取线程池运行状态
       // ~CAPACITY的高三位是1,低29位是0。所以 c & ~CAPACITY 保留了前三位(状态)
        private static int runStateOf(int c)     { return c & ~CAPACITY; }
    
        // 获取线程有效线程数
       // CAPACITY的高三位是0,低29位是1。所以 c & CAPACITY 保留了低29位(线程数)
        private static int workerCountOf(int c)  { return c & CAPACITY; }
    

        由于ThreadPool源码篇幅比较长,所以我打算放到几篇里面来写。要不然一篇时间比较长,读起来大家也会失去耐心。其实ThreadPoolExecutor源码读起来比较容易懂,只要认真去看。大家熟悉了位运算技巧,后面代码逻辑都不是事。
        后期我也会把我读源码中遇到的迷惑的问题抛出来,大家可以一起看一下。有知道的可以评论回答我

    相关文章

      网友评论

        本文标题:ThreadPoolExecutor源码历险-位运算技巧

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