线程池源码——getTask,shutdown,shutdownNow,tryTerminate

getTask获取任务
    //什么情况下会返回null?
    //1.rs >= STOP 成立说明:当前的状态最低也是STOP状态,一定要返回null了
    //2.前置条件 状态是 SHUTDOWN ,workQueue.isEmpty()
    //3.线程池中的线程数量 超过 最大限制时,会有一部分线程返回Null
    //4.线程池中的线程数超过corePoolSize时,会有一部分线程 超时后,返回null。
    private Runnable getTask() {
        //表示当前线程获取任务是否超时 默认false true表示已超时
        boolean timedOut = false; // Did the last poll() time out?

        //自旋
        for (;;) {
            //获取最新ctl值保存到c中。
            int c = ctl.get();
            //获取线程池当前运行状态
            int rs = runStateOf(c);

            // Check if queue empty only if necessary.
            //条件一:rs >= SHUTDOWN 条件成立:说明当前线程池是非RUNNING状态,可能是 SHUTDOWN/STOP....
            //条件二:(rs >= STOP || workQueue.isEmpty())
            //2.1:rs >= STOP 成立说明:当前的状态最低也是STOP状态,一定要返回null了
            //2.2:前置条件 状态是 SHUTDOWN ,workQueue.isEmpty()条件成立:说明当前线程池状态为SHUTDOWN状态 且 任务队列已空,此时一定返回null。
            //返回null,runWorker方法就会将返回Null的线程执行线程退出线程池的逻辑。
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                //使用CAS+死循环的方式让 ctl值 -1
                decrementWorkerCount();
                return null;
            }

            //执行到这里,有几种情况?
            //1.线程池是RUNNING状态
            //2.线程池是SHUTDOWN状态 但是队列还未空,此时可以创建线程。

            //获取线程池中的线程数量
            int wc = workerCountOf(c);

            // Are workers subject to culling?
            //timed == true 表示当前这个线程 获取 task 时 是支持超时机制的,使用queue.poll(xxx,xxx); 当获取task超时的情况下,下一次自旋就可能返回null了。
            //timed == false 表示当前这个线程 获取 task 时 是不支持超时机制的,当前线程会使用 queue.take();

            //情况1:allowCoreThreadTimeOut == true 表示核心线程数量内的线程 也可以被回收。
            //所有线程 都是使用queue.poll(xxx,xxx) 超时机制这种方式获取task.
            //情况2:allowCoreThreadTimeOut == false 表示当前线程池会维护核心数量内的线程。
            //wc > corePoolSize
            //条件成立:当前线程池中的线程数量是大于核心线程数的,此时让所有路过这里的线程,都是用poll 支持超时的方式去获取任务,
            //这样,就会可能有一部分线程获取不到任务,获取不到任务 返回Null,然后..runWorker会执行线程退出逻辑。
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;


            //条件一:(wc > maximumPoolSize || (timed && timedOut))
            //1.1:wc > maximumPoolSize  为什么会成立?setMaximumPoolSize()方法,可能外部线程将线程池最大线程数设置为比初始化时的要小
            //1.2: (timed && timedOut) 条件成立:前置条件,当前线程使用 poll方式获取task。上一次循环时  使用poll方式获取任务时,超时了
            //条件一 为true 表示 线程可以被回收,达到回收标准,当确实需要回收时再回收。

            //条件二:(wc > 1 || workQueue.isEmpty())
            //2.1: wc > 1  条件成立,说明当前线程池中还有其他线程,当前线程可以直接回收,返回null
            //2.2: workQueue.isEmpty() 前置条件 wc == 1, 条件成立:说明当前任务队列 已经空了,最后一个线程,也可以放心的退出。
            if ((wc > maximumPoolSize || (timed && timedOut))
                    && (wc > 1 || workQueue.isEmpty())) {
                //使用CAS机制 将 ctl值 -1 ,减1成功的线程,返回null
                //CAS成功的,返回Null
                //CAS失败? 为什么会CAS失败?
                //1.其它线程先你一步退出了
                //2.线程池状态发生变化了。
                if (compareAndDecrementWorkerCount(c))
                    return null;
                //再次自旋时,timed有可能就是false了,因为当前线程cas失败,很有可能是因为其它线程成功退出导致的,再次咨询时
                //检查发现,当前线程 就可能属于 不需要回收范围内了。
                continue;
            }




            try {
                //获取任务的逻辑


                Runnable r = timed ?
                        workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                        workQueue.take();

                //条件成立:返回任务
                if (r != null)
                    return r;

                //说明当前线程超时了...
                timedOut = true;
            } catch (InterruptedException retry) {
                timedOut = false;
            }
        }
    }

    private void processWorkerExit(Worker w, boolean completedAbruptly) {
        //条件成立:代表当前w 这个worker是发生异常退出的,task任务执行过程中向上抛出异常了..
        //异常退出时,ctl计数,并没有-1
        if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
            decrementWorkerCount();

        //获取线程池的全局锁引用
        final ReentrantLock mainLock = this.mainLock;
        //加锁
        mainLock.lock();
        try {
            //将当前worker完成的task数量,汇总到线程池的completedTaskCount
            completedTaskCount += w.completedTasks;
            //将worker从池子中移除..
            workers.remove(w);
        } finally {
            //释放全局锁
            mainLock.unlock();
        }


        tryTerminate();

        //获取最新ctl值
        int c = ctl.get();
        //条件成立:当前线程池状态为 RUNNING 或者 SHUTDOWN状态
        if (runStateLessThan(c, STOP)) {

            //条件成立:当前线程是正常退出..
            if (!completedAbruptly) {

                //min表示线程池最低持有的线程数量
                //allowCoreThreadTimeOut == true => 说明核心线程数内的线程,也会超时被回收。 min == 0
                //allowCoreThreadTimeOut == false => min == corePoolSize
                int min = allowCoreThreadTimeOut ? 0 : corePoolSize;


                //线程池状态:RUNNING SHUTDOWN
                //条件一:假设min == 0 成立
                //条件二:! workQueue.isEmpty() 说明任务队列中还有任务,最起码要留一个线程。
                if (min == 0 && ! workQueue.isEmpty())
                    min = 1;

                //条件成立:线程池中还拥有足够的线程。
                //考虑一个问题: workerCountOf(c) >= min  =>  (0 >= 0) ?
                //有可能!
                //什么情况下? 当线程池中的核心线程数是可以被回收的情况下,会出现这种情况,这种情况下,当前线程池中的线程数 会变为0
                //下次再提交任务时,会再创建线程。
                if (workerCountOf(c) >= min)
                    return; // replacement not needed
            }

            //1.当前线程在执行task时 发生异常,这里一定要创建一个新worker顶上去。
            //2.!workQueue.isEmpty() 说明任务队列中还有任务,最起码要留一个线程。 当前状态为 RUNNING || SHUTDOWN
            //3.当前线程数量 < corePoolSize值,此时会创建线程,维护线程池数量在corePoolSize个。
            addWorker(null, false);
        }
    }
线程池关闭

shutdown

    public void shutdown() {
        final ReentrantLock mainLock = this.mainLock;
        //获取线程池全局锁
        mainLock.lock();
        try {
            checkShutdownAccess();
            //设置线程池状态为SHUTDOWN
            advanceRunState(SHUTDOWN);
            //中断空闲线程
            interruptIdleWorkers();
            //空方法,子类可以扩展
            onShutdown(); // hook for ScheduledThreadPoolExecutor
        } finally {
            //释放线程池全局锁
            mainLock.unlock();
        }
        tryTerminate();
    }

    private void interruptIdleWorkers() {
        interruptIdleWorkers(false);
    }
    //onlyOne == true 说明只中断一个线程 ,false 则中断所有线程
    //共同前提,worker是空闲状态。
    private void interruptIdleWorkers(boolean onlyOne) {
        final ReentrantLock mainLock = this.mainLock;
        //持有全局锁
        mainLock.lock();
        try {
            //迭代所有worker
            for (Worker w : workers) {
                //获取当前worker的线程 保存到t
                Thread t = w.thread;
                //条件一:条件成立:!t.isInterrupted()  == true  说明当前迭代的这个线程尚未中断。
                //条件二:w.tryLock() 条件成立:说明当前worker处于空闲状态,可以去给它一个中断信号。 目前worker内的线程 在 queue.take() | queue.poll()
                //阻塞中。因为worker执行task时,是加锁的!
                if (!t.isInterrupted() && w.tryLock()) {
                    try {
                        //给当前线程中断信号..处于queue阻塞的线程,会被唤醒,唤醒后,进入下一次自旋时,可能会return null。执行退出相关的逻辑。
                        t.interrupt();
                    } catch (SecurityException ignore) {
                    } finally {
                        //释放worker的独占锁。
                        w.unlock();
                    }
                }
                if (onlyOne)
                    break;
            }

        } finally {
            //释放全局锁。
            mainLock.unlock();
        }
    }

shutdownNow

public List<Runnable> shutdownNow() {
    //返回值引用
    List<Runnable> tasks;
    final ReentrantLock mainLock = this.mainLock;
    //获取线程池全局锁
    mainLock.lock();
    try {
        checkShutdownAccess();
        //设置线程池状态为STOP
        advanceRunState(STOP);
        //中断线程池中所有线程
        interruptWorkers();
        //导出未处理的task
        tasks = drainQueue();
    } finally {
        mainLock.unlock();
    }

    tryTerminate();
    //返回当前任务队列中 未处理的任务。
    return tasks;
}
    private void  interruptWorkers() {
        final ReentrantLock mainLock = this.mainLock;
        //获取线程池全局锁
        mainLock.lock();
        try {
            //遍历所有worker
            for (Worker w : workers)
                //interruptIfStarted() 如果worker内的thread 是启动状态,则给它一个中断信号。。
                w.interruptIfStarted();
        } finally {
            //释放线程池全局锁
            mainLock.unlock();
        }
    }
设置线程池状态 (转化)
final void tryTerminate() {
        //自旋
        for (;;) {
            //获取最新ctl值
            int c = ctl.get();
            //条件一:isRunning(c)  成立,直接返回就行,线程池很正常!
   //条件二:runStateAtLeast(c, TIDYING) 说明 已经有其它线程 在执行 TIDYING -> TERMINATED状态了,当前线程直接回去。
            //条件三:(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty())
            //SHUTDOWN特殊情况,如果是这种情况,直接回去。得等队列中的任务处理完毕后,再转化状态。
            if (isRunning(c) ||
                    runStateAtLeast(c, TIDYING) ||
                    (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
                return;

            //条件成立:当前线程池中的线程数量 > 0
            if (workerCountOf(c) != 0) { // Eligible to terminate
               // 中断空闲线程 其实就是通过中断信号 唤醒阻塞的线程 
                interruptIdleWorkers(ONLY_ONE);
                return;
            }

            final ReentrantLock mainLock = this.mainLock;
            //获取线程池全局锁
            mainLock.lock();
            try {
                //设置线程池状态为TIDYING状态。
                if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
                    try {
                        //调用钩子方法
                        terminated();
                    } finally {
                        //设置线程池状态为TERMINATED状态。
                        ctl.set(ctlOf(TERMINATED, 0));
                        //唤醒调用 awaitTermination() 方法的线程。
                        termination.signalAll();
                    }
                    return;
                }
            } finally {
                //释放线程池全局锁。
                mainLock.unlock();
            }
            // else retry on failed CAS
        }
    }
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值