【Java】线程池技术(三)ThreadPoolExecutor 状态与运行源码解析

ThreadPoolExecutor 状态

ThreadPoolExecutor 继承了 AbstractExecutorService,并实现了 ExecutorService 接口,用于管理线程。内部使用了原子整型 AtomicInteger ctl 来表示线程池状态和 Worker 数量。前 3 位表示线程池状态,后 29 位表示 Worker 数量。

public class ThreadPoolExecutor extends `AbstractExecutorService` {
   
   

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

    private static boolean runStateLessThan(int c, int s) {
   
   
        return c < s;
    }

    private static boolean runStateAtLeast(int c, int s) {
   
   
        return c >= s;
    }

    private static boolean isRunning(int c) {
   
   
        return c < SHUTDOWN;
    }
    
    ......
    
}

由源码中的常量定义可知,ThreadPoolExecutor 有 5 种线程池状态:

  • RUNNING:线程池接收新任务,会执行任务阻塞队列中的任务,ctl 前三位为 111
  • SHUTDOWN:线程池拒绝接收新任务,会执行任务阻塞队列中的任务,ctl 前三位为 000
  • STOP:线程池拒绝接收新任务,不会执行任务阻塞队列中的任务,尝试中断正在执行的任务,ctl 前三位为 001
  • TIDYING:所有任务被关闭,Worker 数量为 0,ctl 前三位为 010
  • TERMINATED:方法 terminated() 执行完毕,ctl 前三位为 011

通过 ctl 的结构可知,其前三位取值对应的线程池状态满足以下关系:

RUNNING < SHUTDOWN < STOP < TIDYING < TERMINATED

因此 runStateLessThan()runStateAtLeast()isRunning() 方法可以很方便的对线程池状态进行判断,不需要考虑当前 Worker 的具体数量。

img

执行任务源码分析

执行任务的方法为 execute(),其源码如下:

public void execute(Runnable command) {
   
   
    if (command == null)
        throw new NullPointerException();
    
    int c = ctl.get();
    // 1.如果正在运行的线程数少于核心线程数,则尝试以给定的操作作为其第一个任务以启动一个新线程。addWorker()的调用以原子方式检查了 runState 和 workerCount,从而防止由于误报 false 而导致的线程增加
    if (workerCountOf(c) < corePoolSize) {
   
   
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }
    // 2.如果一个任务成功加入了阻塞队列,那么我们仍然需要仔细检查是否应该添加一个线程(因为自上次检查以来原有的线程可能已死亡)或自进入此方法以来,线程池已关闭。所以如果重新检查状态已停止,有必要则直接回滚入队操作,或者如果没有正在运行的线程,则启动一个新线程。
    if (isRunning(c) && workQueue.offer(command)) {
   
   
        int recheck = ctl.get();
        
        if (!isRunning(recheck) && remove(command))
            reject(command);
        else if (workerCountOf
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值