触发拒绝策略需同时满足队列已满且活跃线程数达maximumPoolSize,或线程池处于SHUTDOWN/STOP状态;仅队列满或仅线程满均不触发。

任务队列满载后不会自动触发拒绝策略,必须同时满足两个硬性条件:工作队列已满 且 当前活跃线程数已达 maximumPoolSize。只满足其一,线程池仍会继续处理任务。
触发拒绝策略的真实条件
ThreadPoolExecutor 的拒绝逻辑不是“队列满了就拒”,而是按固定顺序尝试任务接纳:
- 新任务提交时,优先尝试加入工作队列(如
ArrayBlockingQueue.offer()) - 若队列 拒绝入队(即
offer()返回false),才进入扩容流程 - 此时若当前线程数 maximumPoolSize,就新建线程执行该任务
- 若线程数已达
maximumPoolSize,且队列又无法接收 → 立即调用RejectedExecutionHandler.rejectedExecution()
为什么有时队列“看起来满了”却不触发?
常见原因在于队列类型和配置不匹配:
-
LinkedBlockingQueue默认无界(容量为Integer.MAX_VALUE),offer()几乎永不返回false,拒绝策略形同虚设 -
PriorityBlockingQueue不重写offer(),内部不检查容量,同样无法触发拒绝 -
SynchronousQueue容量为 0,任务无法排队,直接走扩容路径;一旦线程数达maximumPoolSize就立即拒绝 - 未显式设置有界队列(如
new ArrayBlockingQueue(10)),或corePoolSize与maximumPoolSize不等导致队列满后仍可扩容
如何验证是否真触发了拒绝?
不能只看队列 size 接近上限,要确认两个运行时状态同时成立:
立即学习“Java免费学习笔记(深入)”;
- 调用
executor.getActiveCount() >= maximumPoolSize - 调用
executor.getQueue().size() == queue.capacity()(仅对支持精确 size 的有界队列有效) - 新任务调用
execute()时抛出RejectedExecutionException,或submit().get()捕获该异常
线程池关闭状态下的特殊规则
只要线程池处于 SHUTDOWN 或 STOP 状态,任何新任务提交都会立即触发拒绝策略——此时完全不看队列是否满、线程是否够,这是唯一无需队列+线程双重条件的触发路径。


















