【JUC】ThreadPoolExecutor线程池控制状态ctl

主池控制状态ctl是一个原子整数,包含两个概念字段–
workerCount:指示线程的有效数量。
runState:指示是否运行,关闭等。
即高位中前3位记录runState,后29位记录workerCount。

为了将它们打包成一个int,将workerCount限制为(2^29) -1(约5亿) 线程,而不是(2^31)-1(20亿)。如果将来出现这个问题,可以将变量更改为AtomicLong,并调整下面的shift/mask常量。

但是在需要之前,这段代码使用int会更快更简单一些。workerCount是允许启动而不允许停止的工人数量。该值可能与活动线程的实际数量暂时不同,例如,当ThreadFactory在被要求创建线程时失败,以及退出的线程在终止之前仍在执行簿记时。用户可见的池大小报告为工作集的当前大小。

runState提供了主要的生命周期控制,取值如下:

  • RUNNING:接受新任务和进程排队的任务
  • SHUTDOWN:不接受新任务,但进程排队的任务
  • STOP:不接受新任务,不处理排队的任务,并中断正在进行的任务
  • TIDYING:所有任务都已终止,workerCount为零,线程转换到TIDYING状态将运行terminate()钩子方法terminate。

这些值之间的数字顺序很重要,以便进行有序比较。runState单调地随时间增加,但不需要达到每个状态。
状态之间转换:
在调用SHUTDOWN()时,可能隐含在finalize()中(RUNNING或SHUTDOWN) -> STOP在调用shutdownNow()时,SHUTDOWN -> TIDYING当队列和池都为空时,STOP -> TIDYING当池为空时,TIDYING -> terminate当terminate()钩子方法完成时,在awaitTermination()中等待的线程将在状态达到terminate时返回。检测从SHUTDOWN到TIDYING的转换并不像想的那么简单,因为在SHUTDOWN状态期间,队列可能在非空之后变为空,反之亦然,但是我们只能在看到队列为空之后,看到workerCount为0时终止。

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;

    // 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;

    // Packing and unpacking ctl
    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; }

你可能感兴趣的:(java,java,算法,开发语言)