• 面试官:线程池中多余的线程是如何回收的?


    最近阅读了JDK线程池ThreadPoolExecutor的源码,对线程池执行任务的流程有了大体了解,实际上这个流程也十分通俗易懂,就不再赘述了,别人写的比我好多了。

    不过,我倒是对线程池是如何回收工作线程比较感兴趣,所以简单分析了一下,加深对线程池的理解吧。

    那么,就以JDK1.8为例分析吧。

    1. runWorker(Worker w)

    工作线程启动后,就进入runWorker(Worker w)方法。

    里面是一个while循环,循环判断任务是否为空,若不为空,执行任务;若取不到任务,或发生异常,退出循环,执行processWorkerExit(w, completedAbruptly); 在这个方法里把工作线程移除掉。

    取任务的来源有两个,一个是firstTask,这个是工作线程第一次跑的时候执行的任务,最多只能执行一次,后面得从getTask()方法里取任务。看来,getTask()是关键,在不考虑异常的场景下,返回null,就表示退出循环,结束线程。下一步,就得看看,什么情况下getTask()会返回null。

    (篇幅有限,分段截取,省略中间执行任务的步骤)

    2. getTask() 返回null

    一共有两种情况会返回null,见红框处 。

    第一种情况,线程池的状态已经是STOP,TIDYING, TERMINATED,或者是SHUTDOWN且工作队列为空;

    第二种情况,工作线程数已经大于最大线程数或当前工作线程已超时,且,还有其他工作线程或任务队列为空。这点比较难理解,总之先记住,后面会用。

    下面以条件1和条件2分别指代这两种情况的判断条件。

    3. 分场景分析线程池回收工作线程

    3.1 未调用shutdown() ,RUNNING状态下全部任务执行完成的场景

    这种场景,会将工作线程的数量减少到核心线程数大小(如果本来就没有超过,则不需要回收)。

    比如一个线程池,核心线程数为4,最大线程数为8。一开始是4个工作线程,当任务把任务队列塞满,就得将工作线程增加到8. 当后面任务执行到差不多了,线程取不到任务了,就会回收到4个工作线程的状态(取决于allowCoreThreadTimeOut的值,这里讨论默认值false的情况,即核心线程不会超时。如果为true,工作线程可以全

  • 相关阅读:
    element-ui——select多选框远端搜索组件封装
    新一代爬虫神器puppeteer介绍
    ElementUI浅尝辄止32:NavMenu 导航菜单
    Flink SQL DataGen Connector 示例
    底物多肽Phe-Gly-His-Phe(NO2)-Phe-Ala-Phe-OMe、50572-79-7
    Go | 浅谈包管理模式
    【Linux】gcc/g++ && gdb 使用
    主流前沿的开源监控和报警系统Prometheus+Grafana入门之旅-中
    必备表格软件-FineReport正则表达式简介
    (续)SSM整合之spring笔记(IOC 依赖注入之为属性赋值)(P073—P077)
  • 原文地址:https://blog.csdn.net/weixin_70730532/article/details/126744681