JDK 线程池里真的区分 核心线程与非核心线程吗?

JDK 线程池里真的区分 核心线程与非核心线程吗?
XRJDK 线程池里真的区分 核心线程与非核心线程吗?
不少校招小伙伴对于线程池的了解,大概就是如下图:
- 当核心线程数未满,则新建核心线程执行任务
- 当核心线程数满了,队列未满,则将任务放在等待队列里,等待核心线程去执行
- 当核心线程数满了(但未达最大线程数),队列也满了,新建非核心线程执行任务
- 如果已经达到最大线程数,且队列也满了,则执行饱和策略。
但是这样的了解,可能是不够的。因为这只是一个基础的流程,稍微问细一点、深一点就不够用了。比如,我可能会问下面这些问题:
- 都是知道核心线程默认是不销毁的,那么核心线程在队列中没有任务时,它是什么状态(线程状态),对于操作系统来说会不会分配时间片给它?
- 我们一般自己新创建一个线程,可能使用 new Thread,然后 执行一下 start 方法,然后这个线程 执行完run方法内代码,就销毁了。线程池 ThreadPoolExecutor 中是如何实现 线程复用的?
- 线程池中 区分 核心线程与非线程线程吗?他们数据结构上以及行为上有什么不同。
- 非核心线程是不是只执行 新提交的任务,不消费等待队列中的任务。
这里我详细说说问题3:线程池中 区分 核心线程与非线程线程吗?
实际上从源代码上看,无论是 数据结构还是行为上,其根据没有字段标记这个 线程是核心线程还是非核心线程。线程被包装在一个 Work对象中。这个 Work对象中 包含一个 Thread对象和 一个Runnable对象以及一些其他变量。但是并没有变量去区分这个 work对象是 所谓核心,还是非核心。所以说数据结构上是一致的。
源码中唯一 带有是否核心的变量 就是 下面这个 core。但是它的作用,用于检查 线程数是否超出限制。
因为线程池有两个扩容Work的时机:一个是初始时核心线程的扩容,一个是非核心线程的扩容。
1 | private boolean addWorker(Runnable firstTask, boolean core) |
当核心线程扩容时,用的是 corePoolSize;非核心线程扩容时,用的是maximumPoolSize。
但是在Work运行后,其内部从队列中取任务或者销毁时,并不知道自己当初添加的时候是 当作核心线程来扩容的还是非核心线程扩容的。
我们可以看源码中,final void runWorker(Worker w) 中:
有一个for循环。如果task为空,并且从队列中取不到任务,则结束for循环,进入到 负责清理 Worker和管理线程状态的processWorkerExit方法里。
1 | final void runWorker(Worker w) { |
简单的说:每个Work对象 它是不知道自己的身份的,无论是他获取队列中任务,还是销毁的判断条件。都不依赖于它创建是当作核心线程创建的,还是非核心线程。所以说他们的行为是没有区别的。
判断一个work是否会因为超时销毁,只看 allowCoreThreadTimeOut(是否允许核心线程超时销毁) 和 wc > corePoolSize (当前线程是否超过核心线程数)。只要两个满足其一,就可能因为超时销毁。
1 | boolean timed = allowCoreThreadTimeOut || wc > corePoolSize; |












