ThreadPoolExecutor源码分析(一):重要成员变量

来源:互联网 发布:第一版主网小说网网络 编辑:程序博客网 时间:2024/06/06 04:12

http://blog.csdn.net/lipeng_bigdata/article/details/51232266        

ThreadPoolExecutor是一个通过使用可能几个池线程之一来执行每个提交任务的ExecutorService,这些线程池通常通过Executors工厂方法进行配置。

        ThreadPoolExecutor中的线程池处理了两个不同的问题:

        1、由于减少了每个任务调用的开销,在执行大量的异步任务时它们通常提供改进的性能;

        2、它们提供了边界和管理资源的一种手段,包括多线程,在执行任务集合时的消耗。

        每个ThreadPoolExecutor还维护一些基本的统计数据,例如完成任务的数量。


        一、ThreadPoolExecutor中的重要成员变量

        1、AtomicInteger ctl

        AtomicInteger类型的ctl代表了ThreadPoolExecutor中的控制状态,它是一个复核类型的成员变量,是一个原子整数,借助高低位包装了两个概念:

        (1)workerCount:线程池中当前活动的线程数量,占据ctl的低29位;

        (2)runState:线程池运行状态,占据ctl的高3位,有RUNNING、SHUTDOWN、STOP、TIDYING、TERMINATED五种状态。

        AtomicInteger ctl的定义如下:

[java] view plain copy
  1. private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));  

        先说下workerCount:线程池中当前活动的线程数量,它占据ctl的低29位,这样,每当活跃线程数增加或减少时,ctl直接做相应数目的增减即可,十分方便。而ThreadPoolExecutor中COUNT_BITS就代表了workerCount所占位数,定义如下:

[java] view plain copy
  1. private static final int COUNT_BITS = Integer.SIZE - 3;  
        在Java中,一个int占据32位,而COUNT_BITS的结果不言而喻,Integer大小32减去3,就是29;另外,既然workerCount代表了线程池中当前活动的线程数量,那么
它肯定有个上下限阈值,下限很明显就是0,上限呢?ThreadPoolExecutor中CAPACITY就代表了workerCount的上限,它是ThreadPoolExecutor中理论上的最大活跃线程数,其定义如下:

[java] view plain copy
  1. private static final int CAPACITY   = (1 << COUNT_BITS) - 1;  
        运算过程为1左移29位,也就是00000000 00000000 00000000 00000001 --> 001 0000 00000000 00000000 00000000,再减去1的话,就是 000 11111 11111111 11111111 11111111,前三位代表线程池运行状态runState,所以这里workerCount的理论最大值就应该是29个1,即536870911;

        既然workerCount作为其中一个概念复合在AtomicInteger ctl中,那么ThreadPoolExecutor理应提供从AtomicInteger ctl中解析出workerCount的方法,如下:

[java] view plain copy
  1. private static int workerCountOf(int c)  { return c & CAPACITY; }  
        计算逻辑很简单,传入的c代表的是ctl的值,即高3位为线程池运行状态runState,低29位为线程池中当前活动的线程数量workerCount,将其与CAPACITY进行与操作&,也就是与000 11111 11111111 11111111 11111111进行与操作,c的前三位通过与000进行与操作,无论c前三位为何值,最终都会变成000,也就是舍弃前三位的值,而c的低29位与29个1进行与操作,c的低29位还是会保持原值,这样就从AtomicInteger ctl中解析出了workerCount的值。
        接下来,我们再看下runState:线程池运行状态,它占据ctl的高3位,有RUNNING、SHUTDOWN、STOP、TIDYING、TERMINATED五种状态。我们先分别解释下这五种状态:

        (1)RUNNING:接受新任务,并处理队列任务

[java] view plain copy
  1. private static final int RUNNING    = -1 << COUNT_BITS;  
        -1在Java底层是由32个1表示的,左移29位的话,即111 00000 00000000 00000000 00000000,也就是低29位全部为0,高3位全部为1的话,表示RUNNING状态,即-536870912;

        (2)SHUTDOWN:不接受新任务,但会处理队列任务

[java] view plain copy
  1. private static final int SHUTDOWN   =  0 << COUNT_BITS;  
        0在Java底层是由32个0表示的,无论左移多少位,还是32个0,即000 00000 00000000 00000000 00000000,也就是低29位全部为0,高3位全部为0的话,表示SHUTDOWN状态,即0;

        (3)STOP:不接受新任务,不会处理队列任务,而且会中断正在处理过程中的任务

[java] view plain copy
  1. private static final int STOP       =  1 << COUNT_BITS;  

        1在Java底层是由前面的31个0和1个1组成的,左移29位的话,即001 00000 00000000 00000000 00000000,也就是低29位全部为0,高3位为001的话,表示STOP状态,即536870912;

        (4)TIDYING:所有的任务已结束,workerCount为0,线程过渡到TIDYING状态,将会执行terminated()钩子方法

[java] view plain copy
  1. private static final int TIDYING    =  2 << COUNT_BITS;  
        2在Java底层是由前面的30个0和1个10组成的,左移29位的话,即010 00000 00000000 00000000 00000000,也就是低29位全部为0,高3位为010的话,表示TIDYING状态,即1073741824;

        (5)TERMINATED:terminated()方法已经完成

[java] view plain copy
  1. private static final int TERMINATED =  3 << COUNT_BITS;  
        2在Java底层是由前面的30个0和1个11组成的,左移29位的话,即011 00000 00000000 00000000 00000000,也就是低29位全部为0,高3位为011的话,表示TERMINATED状态,即1610612736;

        由上面我们可以得知,运行状态的值按照RUNNING-->SHUTDOWN-->STOP-->TIDYING-->TERMINATED顺序值是递增的,这些值之间的数值顺序很重要。随着时间的推移,运行状态单调增加,但是不需要经过每个状态。那么,可能存在的线程池状态的转换是什么呢?如下:

        (1)RUNNING -> SHUTDOWN:调用shutdownNow()方法后,或者线程池实现了finalize方法,在里面调用了shutdown方法,即隐式调用;

        (2)(RUNNING or SHUTDOWN) -> STOP:调用shutdownNow()方法后;

        (3)SHUTDOWN -> TIDYING:线程池和队列均为空时;

        (4)STOP -> TIDYING:线程池为空时;

        (5)TIDYING -> TERMINATED:terminated()钩子方法完成时。

        我们再来看下是实现获取运行状态的runStateOf()方法,代码如下:

[java] view plain copy
  1. private static int runStateOf(int c)     { return c & ~CAPACITY; }  
        ~是按位取反的意思,CAPACITY表示的是高位的3个0,和低位的29个1,而~CAPACITY则表示高位的3个1,2低位的9个0,然后再与入参c执行按位与操作,即高3位保持原样,低29位全部设置为0,也就获取了线程池的运行状态runState。

        最后,我们再看下原子变量ctl的初始化方法ctlOf(),代码如下:

[java] view plain copy
  1. private static int ctlOf(int rs, int wc) { return rs | wc; }  
        很简单,传入的rs表示线程池运行状态runState,其是高3位有值,低29位全部为0的int,而wc则代表线程池中有效线程的数量workerCount,其为高3位全部为0,而低29位有值得int,将runState和workerCount做或操作|处理,即用runState的高3位,workerCount的低29位填充的数字,而默认传入的runState、workerCount分别为RUNNING和0。
        2、BlockingQueue<Runnable> workQueue

        workQueue是用于持有任务并将其转换成工作线程worker的队列;

        3、HashSet<Worker> workers

        workers是包含线程池中所有工作线程worker的集合,仅仅当拥有mainLock锁时才能访问它;

        4、long completedTaskCount

        completedTaskCount是已完成任务的计数器,只有在worker线程的终止,仅仅当拥有mainLock锁时才能访问它;

        5、volatile ThreadFactory threadFactory

        创建新线程的工厂类;

        6、volatile RejectedExecutionHandler handler

        执行过程中shutdown时调用的handler;

        7、volatile long keepAliveTime

        空闲线程等待工作的超时时间(纳秒),即空闲线程存活时间;

        8、volatile boolean allowCoreThreadTimeOut

        默认值为false,如果为false,core线程在空闲时依然存活;如果为true,则core线程等待工作,直到时间超时至keepAliveTime;

        9、volatile int corePoolSize

        核心线程池大小,保持存活的工作线程的最小数目,当小于corePoolSize时,会直接启动新的一个线程来处理任务,而不管线程池中是否有空闲线程;

        10、volatile int maximumPoolSize

        线程池最大大小,也就是线程池中线程的最大数量。

原创粉丝点击