线程池的源码解析之execute方法解析

上一段自己打了注释的源码吧 jdk版本是11和8的略有不同
线程池的一些属性和方法

// 记录线程池的状态信息 高三位是状态信息,其余位表示工作的worker数量
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
// 表示worker数量的位数也就是上面说的  其余位
private static final int COUNT_BITS = Integer.SIZE - 3;
// 求worker数量的掩码 1 左移 COUNT_BITS - 1
private static final int COUNT_MASK = (1 << COUNT_BITS) - 1;
/*
* 计算woker的数量
* 按照现行的jdk(Integer.SIZE是32) COUNT_MASK就是 0001 1111 1111 1111 1111 1111 1111 1111 
* ctl 与上这个就可以求出woker的数量
*/
private static int workerCountOf(int c)  { return c & COUNT_MASK; }

execute方法 代码不多但是说到很多

public void execute(Runnable command) {
    // 要提交的任务不能是null
    if (command == null)
        throw new NullPointerException();
    // 获取ctl的值
    int c = ctl.get();
    // 如果当前woker的数量小于 核心线程数 则该判断为true
    if (workerCountOf(c) < corePoolSize) {
        /*
        * 使用核心线程数的限制去开worker来执行这个任务 
        * 注意没有核心线程和非核心线程这一说 worker是没有区别的
        * addWorker会失败 这里只需要了解 可能是因为线程池状态或者worker的数量引起addWorker失败
        * 因为可能不只是一个线程在操作线程池可能其他线程也在操作
        */
        if (addWorker(command, true))
            return;
        // 如果addWorker失败则ctl要重新获取因为不管是状态变还是worker数量变ctl都已经变了你需要重新获取最新值
        c = ctl.get();
    }
    /*
    * 在当前worker数量大于等于corePoolSize或者上面的addWorker失败之后才会走到这里
    * 经过上面分析可能有两种可能 1、线程的状态发生改变  2、当前worker数量不小于核心线程数
    * 第一个判断是查看一下当前线程的状态是否是running状态
    * 在满足第一条件下会尝试往工作队列里面添加这个任务 但是有可能失败 工作队列可能满了
    */ 
    if (isRunning(c) && workQueue.offer(command)) {
        // 走到这里说明offer之前是running状态 放入工作队列成功了 需要重新获取当前状态 因为有可能放进去之后线程状态变了
        int recheck = ctl.get();
        /*
        * 如果offer之后线程池不是running了 需要尝试remove刚才的任务
        * 不是running的状态下 remove也有可能失败,他可能被执行了
        */
        if (! isRunning(recheck) && remove(command))
            // 如果remove成功了需要拒绝这个任务
            reject(command);
        /*
        * 因为走到这里一定是 offer成功了 
        * 这个判断是为了防止没有worker 但是队列里面有任务 没人执行
        * 这个是有可能的 工作一段时间后worker的数量为0 和 allowCoreThreadTimeOut()这个方法有关系
        * 
        * 上一个if判断的!isRuning 是true remove失败的时候 有可能 workerCountOf(recheck) == 0 为true
        * 这个时候线程池肯定是不让你再添加线程的
        */
        else if (workerCountOf(recheck) == 0)
            /* 
            * 如果出现 线程池是running worker是0 队列有任务 需要添加一个worker执行这些任务
            * 如果出现 线程池不是running 但是remove失败 worker是0 线程池是不允许添加worker的这个逻辑在addworker方法里面
            *
            */
            addWorker(null, false);
    }
    /*
    * 如果用核心线程数限制开worker执行任务失败
    * 或者 线程池状态不是running
    * 或者 工作队列已经满了
    * 使用最大线程数限制开worker执行任务
    */
    else if (!addWorker(command, false))
        // 失败的原因有 1、worker达到非核心线程数 2、线程池的状态变了不是running了 则拒绝这个任务
        reject(command);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值