别乱用!线程池拒绝策略选错,系统可能直接崩!

原文来自于:zha-ge.cn/java/101

别乱用!线程池拒绝策略选错,系统可能直接崩!

最近遇到一件小刺激的事,分享下血泪故事。线程池这玩意,Java八股文里都念过,构造参数有个啥 RejectedExecutionHandler,平时懒得理,new ThreadPoolExecutor 反正贴个 AbortPolicy,一脸天真地以为天塌下来也只是打个异常。直到......踩进大坑,差点全组请饮茶。


话说我们有个数据同步服务,需求特别朴实------爬数据、多线程处理入库完事。线程池设了:

  • core 10
  • max 30
  • queue 1000
  • new ThreadPoolExecutor(..., new ThreadPoolExecutor.AbortPolicy())

很标准是不是?写完开开心心上线。

管不住的骚操作

但某天业务方突发奇想:高峰期可能瞬间几千条数据灌进来。"没事线程池嘛,阿里说要有队列限制",我心想,这队列顶多慢点嘛。当时还特豪气和同事说:"不怕,最大线程都30,还能撑一会。"

高峰来了,日志看着看着不对劲:

复制代码
java.util.concurrent.RejectedExecutionException

那个熟悉的红字,像欠钱的债主一样突然弹满了日志。然后业务方开始反馈------数据漏同步,而且一些告警也开始响了。

踩坑瞬间

回头扒代码,线索很快就浮出水面。

  • 线程池不够用,队列也爆了,直接走了 AbortPolicy。
  • 任务直接砍掉,消息石沉大海。
  • 日志一堆异常,业务数据丢失还不自知。

心里一万匹草泥马奔腾:AbortPolicy 真这么野蛮?

接着脑补另几个拒绝策略:

  • CallerRunsPolicy:让提交任务的线程自己"顶上",主线程甚至 HTTP 请求线程可能被卡死。
  • DiscardPolicy:直接静默丢弃,凉凉。
  • DiscardOldestPolicy:丢掉队列最早的任务,也不一定比直接Abort好多少。

代码片段(小心点看,这就是个小坑货):

java 复制代码
ThreadPoolExecutor pool = new ThreadPoolExecutor(
    10, 30, 30, TimeUnit.SECONDS,
    new LinkedBlockingQueue<>(1000),
    new ThreadPoolExecutor.AbortPolicy() // 就是这家伙
);

意外的灵感

老司机拍了拍我肩膀,说:"别光会默认值,策略配合场景选,别拍脑门!"

我想了想,如果用了 CallerRunsPolicy,主线程提交失败任务自己跑,这样虽然慢,但最起码不会直接丢任务。

java 复制代码
new ThreadPoolExecutor(
    10, 30, 30, TimeUnit.SECONDS,
    new LinkedBlockingQueue<>(1000),
    new ThreadPoolExecutor.CallerRunsPolicy()
)

但要小心"反向堵塞":主线程一旦卡住,后续没法进,压力会逐步释放。

经验启示

踩过这坑,特别想提醒:

  • 选拒绝策略前务必想清楚:你的业务能不能丢任务?丢了怎么补?

  • 高并发、强一致场景,建议日志告警+落地补偿,不要啥都交给默认策略。

  • 拒绝策略选型建议表:

    场景 推荐策略 备注
    数据绝不能丢 CallerRunsPolicy 慢,但安全
    允许部分丢失,追求时效 Discard或DiscardOldest 必须有补偿机制
    只想打断任务 AbortPolicy 监控需到位
  • 上线前一定压测,别拿生产数据当火锅底料。

  • 日志里异常别无视,"RejectedExecutionException" 明显就要管。

最后的碎碎念

线程池策略是个"小配置",但用错了就是定时炸弹。配置这些细节,一定要和业务场景连起来想。别像我,被一个 abort 弹窗教育做人。行吧,今天 rant 到这,溜了------得继续填昨天那些"被拒绝"的数据坑去。

别乱用默认值,你的锅盘不一定结实!

相关推荐
endswel21 分钟前
Spring bean 注册多种方式
java·后端·spring
鬼手点金35 分钟前
opencode-性能优化建议
java·人工智能·git·自动化·nanogpt
聪明蛋子哟35 分钟前
Python与Java双栈实战:手撸一个支持RAG与Tool Calling的高性能Agent框架
java·开发语言·python
xuxigifxfh40 分钟前
HJ4 字符串分隔
java·开发语言·华为机考
写后端的胖头鱼1 小时前
Java 反射详解 + 场景示例
java·反射
零基础1231 小时前
PDF 处理工具全攻略:pdf24、PDFgear、Adobe Acrobat DC 与 Stirling-PDF 深度对比
java·开发语言·pdf
SL_staff1 小时前
制造业数字化协同:为什么甘特图只是起点,不是终点
java·开源·全栈
anew___2 小时前
《从零手写操作系统 (29):管道与重定向进阶——命名管道、Here Document与Shell语法扩展》
java·开发语言·前端·javascript·网络
Mikko72 小时前
JVM 线上排查实战(六):JFR 怎么用?JDK 8 要不要加 UnlockCommercialFeatures、jfr 命令在哪、录的文件为什么读不了
java·运维·jvm·后端
奇牙coding2 小时前
GPT-5.5 API 报 401 但 GPT-5.4 正常怎么办?不是 Key 失效,是 Organization 头的强制校验变了
java·网络·gpt·ai