关于JDK线程池非核心线程如何死亡
»jdk目录:
问题来源
今天面试被问到线程池中keepAliveTime的实现方式
也就是怎么实现非核心线程超时死亡的
还是去年看过线程池的源码,后来忘了。我就说了我不太清楚,他说让我自己实现清除线程池中的非核心线程怎么做
我说,线程肯定是保存在一个worker Set里面,我不知道里面线程有没有标识自己是核心还是非核心,
只要把里面的非核心线程指针引用置为null,让虚拟机自己去回收。
面试官就没继续问了。
下来之后,我看了一下源码,发现跟我想的完全不一样。
线程池工作模式
当提交一个任务(Runnable),线程池会先判断当前Worker数目是否达到核心线程数
- 如果没有达到核心线程数就添加一个Worker,并且让这个Worker启动。
- 如果达到了核心线程数,那么判断线程池是否还在Running状态,并且尝试将当前任务添加到任务队列中
- 如果添加失败了,那么尝试新建Worker,如果新建Worker失败了,那么执行拒绝策略 而一个Worker启动之后,并没有线程回收这个Worker,这个Worker会一直从任务队列中取任务,执行,取任务,执行,当取任务失败,也就是取任务返回null的时候,这个worker就会退出,并且将自己从Worker Set中remove。
而取任务的逻辑是先判断当前线程数是否超过核心线程数,如果超过核心线程数,会调用poll方法取任务,否则调用take方法取任务(会一直阻塞),所以只有当当前Worker数目大于核心线程数的时候,取任务才会返回null,此时,将这个Worker从线程池中移除,并退出。
所以,其实并没有核心线程和非核心线程这个说法,任何一个线程它都可能会被当作非核心线程。
总结
线程池的实现方式其实并不复杂,但是其中用了很多优化的方法,让它工作的更好。
同时里面也有很多细节,比如可能会有多个线程同时退出了,而导致线程数小于核心线程数,所以线程退出的的时候还会有addWorker。