线程池有哪些拒绝策略?

考查重点:饱和处理与背压行为。Abort抛异常、CallerRuns调用方执行、Discard丢新、DiscardOldest弃队头再试;选法需匹配任务可丢性与背压

本题目录

参考答案

核心回答

以 Java ThreadPoolExecutor 为例,线程池关闭,或者运行时队列无法接收新任务、又无法继续增加工作线程时,会调用 RejectedExecutionHandler。JDK 提供四种内置策略,默认是 AbortPolicy:

  1. AbortPolicy: 向提交任务的线程抛出 RejectedExecutionException,让调用方知道这次提交失败,适合需要明确失败反馈的场景。
  2. CallerRunsPolicy: 在线程池尚未关闭时,由提交任务的线程直接执行;提交者被占住,有机会减慢后续提交速度。线程池已经关闭时会丢弃任务,并非任何情况下都保证执行。
  3. DiscardPolicy: 静默丢弃当前被拒绝的任务。只适合确实允许丢弃、且不依赖该任务完成结果的工作。
  4. DiscardOldestPolicy: 线程池未关闭时,移除工作队列头部任务,再尝试提交当前任务;关闭时丢弃当前任务。它丢的是排队任务,不是已经执行最久的任务,重试也不保证成功。

还可以自定义 RejectedExecutionHandler,按业务返回失败、登记可靠待处理记录或做受控降级。策略的选择要回答两个问题:任务能否丢,提交者能否承受同步执行的延迟。

CallerRuns 什么情况下能形成背压

例如批处理线程不断提交任务,当池饱和后,它被迫自己执行一项任务,下一次提交就推迟了,可能自然降低上游速度。

但如果提交者是 Web 请求线程或事件循环,长任务会占住入口执行资源,扩大接口延迟;若提交者已经持有锁或数据库事务,还会延长这些资源的占用。上游如果由大量独立提交者持续灌入,单个提交者变慢也未必能控制总体流量。

因此,CallerRuns 是一种有条件的反馈机制,不等于可靠队列、自动限流或“不丢任务”的承诺。执行线程改变后,线程上下文和调用耗时也可能与原来的异步路径不同。

为什么静默丢弃可能导致 Future 一直等

submit 通常先把任务包装成 FutureTask,再交给 execute。如果拒绝处理只是丢弃这个包装任务,既没有执行,也没有把它标记为完成或取消,返回的 Future 就可能一直未完成,无限等待的 get 也可能一直不返回。

DiscardOldest 丢掉的排队任务也可能存在同样问题。依赖结果的业务应获得明确的拒绝反馈;自定义处理若选择丢弃,需要按约定取消相应 Future、记录结果并通知等待方。调用 get 的等待超时本身不会自动取消任务,仍需根据业务处理后续状态。

DiscardOldest 的“最老”如何理解

内置实现调用的是队列的 poll,再执行一次 execute。对于普通 FIFO 队列,队首通常是最早等待的任务;对于优先级队列,队首可能是优先级最高的任务,所以不能不看队列语义就使用。

而且重试期间其他线程仍可能提交任务,重试可以再次触发拒绝,不能理解为腾出一个位置后新任务就一定成功。自定义策略也不宜无限重试,或在同一个已饱和的线程池里再排一个“处理拒绝”的任务;阻塞等待队列空位还可能与池内任务互相等待。

怎样结合业务选择

需要明确结果的在线请求,可以用快速失败配合上游限流、可控重试;不可丢失的后台工作,应先可靠登记任务,再由可恢复流程处理,不能只靠进程内队列和拒绝回调。

过期采样、可覆盖的刷新等允许丢弃的任务,可以设计丢弃或合并,但仍应统计拒绝数、队列等待时间和任务失败。无界队列通常不会因队满触发饱和拒绝,却可能长期堆积到内存不足;改大队列不等于解决容量问题。

四种策略都是 ThreadPoolExecutor 的静态内部类,实现 RejectedExecutionHandler 接口。业务自定义策略实现的是这个接口的 rejectedExecution 方法,不需要修改线程池源码。

参考资料

相关面经

9 篇

科大讯飞

后端开发工程师
一面、二面、三面
查看原面经 →
线程池核心线程满、队列满、最大线程数也满,再提交任务会发生什么?拒绝策略有哪些?

水滴公司

AI全栈工程师
校招秋招一面
查看原面经 →
拒绝策略里"放弃第一个"是啥意思?是放弃当前这个吗?
追问
"放弃最后一个"是啥?

华盛通

Java实习生
实习
查看原面经 →
拒绝策略有哪几种?

科大讯飞

Java 开发
一面
查看原面经 →
拒绝策略有哪些?

字节跳动

全栈
一面
查看原面经 →
拒绝策略都有哪些?你觉得这四种拒绝策略分别适用于哪些场景呢?
展开剩余 4 篇面经

靖安科技

后端工程师(RAG/Agent 项目)
秋招一面
查看原面经 →
追问
拒绝策略实现在哪个类

蚂蚁集团

面经合集
查看原面经 →
追问
知道哪几种拒绝策略,基于什么样的场景会去选择这样的拒绝策略

万兴科技

Android 客户端开发工程师(AI 方向)
实习一面
查看原面经 →
线程池拒绝策略有哪几种?

字节跳动

后端开发工程师
一面
查看原面经 →
线程池有哪些拒绝策略?
追问
各种线程池拒绝策略分别是如何处理任务的?

相关题目

4 题