线程池关闭流程

线程池的状态转换:在这里插入图片描述

在这里插入图片描述

关闭线程池的方法
  • shutdown():把线程池状态修改为SHUTDOWN,并通过interruptIdleWorkers()中断所有空闲工作者线程。
  • shutdownNow():把线程池状态修改为STOP,移除队列中的任务并通过interruptWorkers()中断所有工作者线程。

  shutdownNow()会中断正在工作的工作者线程,也仅仅是中断目标线程,但目标线程不一定响应中断或者已处理中断异常,它并不是停止目标线程。

线程池是如何判断工作者线程是空闲还是忙碌呢?

  工作者线程Worker是继承AbstractQueuedSynchronizerd的,锁被占用时线程就是忙碌状态,锁空闲时线程就是空闲状态。

为什么要中断工作者线程?

  中断空闲的工作者线程:因为线程可能在getTask()中的take()或者poll()方法处阻塞,通过中断就能够唤醒这些被阻塞的线程,然后这些被唤醒线程如果获取不到任务的话,就会被回收。
  中断忙碌的工作者线程:主要是为了取消任务的执行,但不一定成功,因为任务不一定响应中断或则处理了中断异常。

线程池关闭的流程

  在执行任何可能终止线程池的操作都会调用tryTerminate()去尝试关闭线程池,比如:

  • processWorkerExit():工作者线程退出
  • remove():移除队列中的某个任务
  • purge():移除队列中已取消的任务
  • shutdown():拒绝提交任务
  • shutdownNow():拒绝提交任务并移除队列中的任务
tryTerminate()源码解析:
final void tryTerminate() {
        for (;;) {
        	//线程池状态
            int c = ctl.get();
            // 线程池是运行状态
            if (isRunning(c) ||
            	// 线程池是TIDYING或者TERMINATED状态
                runStateAtLeast(c, TIDYING) ||
                // 线程池是SHUTDOWN但是队列中还有任务
                (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
                return;
            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));
                        termination.signalAll();
                    }
                    return;
                }
            } finally {
                mainLock.unlock();
            }
            // else retry on failed CAS
        }
    }

总结

  • 线程池的状态为SHUTDOWN或STOP任务队列为空工作者线程数为0时,线程池就会进入TIDYING状态,当执行完terminated()方法后,就会进入最终的TERMINATED状态。
  • 如果任务是一个死循环且不响应中断的话,那么这个线程池永远也不会被关闭。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值