【JDK源码分析系列】ThreadPoolExecutor 源码解析 -- 线程池终止
发布日期:2021-05-07 20:51:25 浏览次数:20 分类:原创文章

本文共 4761 字,大约阅读时间需要 15 分钟。

【JDK源码分析系列】ThreadPoolExecutor 源码解析 -- 线程池终止

【1】线程池终止

【1.1】ThreadPoolExecutor -- shutdown

//shutdown() -- 温柔的终止线程池public void shutdown() {    final ReentrantLock mainLock = this.mainLock;    mainLock.lock();    try {        //判断调用者是否有权限shutdown线程池        checkShutdownAccess();        //CAS+循环设置线程池状态为shutdown        advanceRunState(SHUTDOWN);        //中断所有空闲线程        interruptIdleWorkers();        //shutdown 回调方法        //由子类实现        onShutdown(); // hook for ScheduledThreadPoolExecutor    } finally {        mainLock.unlock();    }    //尝试终止线程池    tryTerminate();}
private void checkShutdownAccess() {    SecurityManager security = System.getSecurityManager();    if (security != null) {        security.checkPermission(shutdownPerm);        final ReentrantLock mainLock = this.mainLock;        mainLock.lock();        try {            for (Worker w : workers)                security.checkAccess(w.thread);        } finally {            mainLock.unlock();        }    }}private void advanceRunState(int targetState) {    for (;;) {        int c = ctl.get();        if (runStateAtLeast(c, targetState) ||            ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))            break;    }}//回收空余线程//onlyOne如果为true,最多interrupt一个worker//只有当终止流程已经开始,但线程池还有worker线程时,tryTerminate()方法会做调用onlyOne为true的调用//(终止流程已经开始指的是:shutdown状态且workQueue为空或者stop状态)//在这种情况下,最多有一个worker被中断,为了传播shutdown信号,以免所有的线程都在等待//为保证线程池最终能终止,这个操作总是中断一个空闲worker//而shutdown()中断所有空闲worker,来保证空闲线程及时退出private void interruptIdleWorkers(boolean onlyOne) {    final ReentrantLock mainLock = this.mainLock;    mainLock.lock();    try {        //循环回收,onlyOne=false,说明要回收很多个        for (Worker w : workers) {            Thread t = w.thread;            //线程没有被打断,并且worker可以获得锁,那么当前线程可以被打断            if (!t.isInterrupted() && w.tryLock()) {                try {                    //建议线程中断                    t.interrupt();                } catch (SecurityException ignore) {                } finally {                    w.unlock();                }            }            if (onlyOne)                //退出循环                break;        }    } finally {        mainLock.unlock();    }}//试图终止//在以下情况将线程池变为TERMINATED终止状态//shutdown且正在运行的worker和workQueue队列都empty//stop且没有正在运行的worker////这个方法必须在任何可能导致线程池终止的情况下被调用,如://减少worker数量//shutdown时从queue中移除任务//这个方法不是私有的,所以允许子类ScheduledThreadPoolExecutor调用final void tryTerminate() {    for (;;) {        int c = ctl.get();        //正在运行        if (isRunning(c) ||            //tidying  terminated            runStateAtLeast(c, TIDYING) ||            //shutdown 且 队列不为空            (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))            //综合上面3个条件,可以推断出当线程池stop或者shutdown            //且任务队列为空,就可以去terminated了            return;        //worker的数量不为零,说明还有任务在执行,所以先不要terminated线程池        if (workerCountOf(c) != 0) { // Eligible to terminate            interruptIdleWorkers(ONLY_ONE);            return;        }        //如果状态是SHUTDOWN,workQueue也为空了,正在运行的worker也没有了,开始terminated        final ReentrantLock mainLock = this.mainLock;        mainLock.lock();        try {            //CAS:将线程池的ctl变成TIDYING(所有的任务被终止,workCount为0,为此状态时将会调用terminated()方法),            //期间ctl有变化就会失败,会再次for循环            if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {                try {                    //终止线程, 由子类实现                    terminated();                } finally {                    //将线程池的ctl变成TERMINATED                    ctl.set(ctlOf(TERMINATED, 0));                    //唤醒调用等待线程池终止的线程awaitTermination()                    termination.signalAll();                }                return;            }        } finally {            mainLock.unlock();        }        // else retry on failed CAS        // 如果上面的CAS判断false,再次循环    }}

【1.2】ThreadPoolExecutor -- shutdownNow

//shutdownNow() -- 强硬的终止线程池public List<Runnable> shutdownNow() {    List<Runnable> tasks;    final ReentrantLock mainLock = this.mainLock;    mainLock.lock();    try {        //判断调用者是否有权限shutdown线程池        checkShutdownAccess();        //CAS+循环设置线程池状态为stop        advanceRunState(STOP);        //中断所有线程,包括正在运行任务的        interruptWorkers();        //将workQueue中的元素放入一个List并返回        tasks = drainQueue();    } finally {        mainLock.unlock();    }    //尝试终止线程池    tryTerminate();    return tasks;}
//变量所有的 worker 并中断这些 workerprivate void interruptWorkers() {    final ReentrantLock mainLock = this.mainLock;    mainLock.lock();    try {        for (Worker w : workers)            w.interruptIfStarted();    } finally {        mainLock.unlock();    }}

【1.3】ThreadPoolExecutor -- awaitTermination

当前线程阻塞,直到
等所有已提交的任务(包括正在跑的和队列中等待的)执行完
或者等超时时间到
或者线程被中断,抛出InterruptedException
然后返回true(shutdown请求后所有任务执行完毕)或false(已超时)

参考致谢
本博客为博主的学习实践总结,并参考了众多博主的博文,在此表示感谢,博主若有不足之处,请批评指正。

【1】

【2】

上一篇:【网络通信 -- 直播】网络通信协议简介 -- IP 网际协议
下一篇:【JDK源码分析系列】ThreadPoolExecutor 源码解析 -- 任务提交与运行

发表评论

最新留言

初次前来,多多关照!
[***.217.46.12]2025年04月08日 22时40分59秒