核心线程数优先创建并常驻,最大线程数仅在队列满且线程未达上限时作为弹性后备创建;队列类型决定扩容时机,拒绝策略是资源耗尽时的最终处理机制。

核心线程数和最大线程数不是并列关系,而是分阶段、有优先级的协作机制:核心线程是“常驻主力”,最大线程是“弹性后备”,中间靠任务队列做缓冲和触发开关。
核心线程先上岗,不看空闲只看数量
新任务提交时,线程池第一反应是检查当前运行线程是否少于 corePoolSize。只要没达到这个数,就立刻创建新线程——哪怕已有线程正空闲着,也不会复用它去接任务。这些线程默认长期存活,不因空闲而销毁(除非显式开启 allowCoreThreadTimeOut(true))。
队列是扩容的“门槛”,不是缓存区
只有当核心线程全忙后,新任务才尝试进 workQueue。但能否进、进后是否触发扩容,取决于队列类型:
-
SynchronousQueue:容量为0,任务无法入队 → 直接触发扩容(只要未达
maximumPoolSize) - ArrayBlockingQueue:固定容量,填满后才允许创建非核心线程
-
LinkedBlockingQueue(无界):任务无限堆积 →
maximumPoolSize失效,极易引发内存溢出
最大线程数只在队列满后生效
非核心线程不会提前出现,只在满足两个条件时才被创建:
- 工作队列已满(或根本无法入队)
- 当前总线程数仍小于 maximumPoolSize
这类线程是“临时工”:空闲超过 keepAliveTime 就会被回收,目的是应对突发流量,而非长期承载。
拒绝策略是最终防线,不是容错兜底
当队列满 + 线程已达 maximumPoolSize,新任务就彻底无处安放。此时拒绝策略(如 AbortPolicy 抛异常、CallerRunsPolicy 回退到调用线程)才起作用。它反映的是你对系统稳定性的取舍,而不是补救配置失误的手段。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











