当前位置: 首页 > news >正文

线程池RejectedExecutionException异常

文章目录

  • 1、报错
  • 2、定位
  • 3、修复
  • 4、线程池使用的一点思考

1、报错

检索项目日志时,发现一个异常堆栈信息,核心报错:

java.util.concurrent.RejectedExecutionException: 
Task java.util.concurrent.CompletableFuture$AsyncSupply@480a10c7 
rejected from java.util.concurrent.ThreadPoolExecutor@51313448
[Running, pool size = 32, active threads = 32, queued tasks = 200, completed tasks = 2487]
// ...

关键字:RejectedExecutionException,从这个异常可以看出,这是因为往线程池提交的任务数量超过了最大线程数 + 阻塞队列长度,然后任务再提交过来,线程池无法再接收新的任务,走了默认的拒绝策略 AbortPoligy:直接抛出RejectedExecutionExption异常阻止系统正常运行

2、定位

查看堆栈信息里的信息,定位到异常代码出自:

@Service
public class InspectionService {private static final Logger log = LoggerFactory.getLogger(InspectionService.class);private final ExecutorService pool = new ThreadPoolExecutor(16,		// 常驻线程数量32,		// 最大线程数量10,		// 线程存活时间,线程多长时间没被使用就关闭TimeUnit.SECONDS,	// 上一个参数的单位new LinkedBlockingQueue<>(200),		// 阻塞队列new ThreadFactoryBuilder().setNameFormat("InspectionService-%d").build(),	// 线程工厂对象new ThreadPoolExecutor.AbortPolicy()		// 拒绝策略);
// ....

再下面CompleteableFuture再提交任务到线程池:

CompletableFuture.supplyAsync(() -> service.queryGroupInfo(), pool)
//....

提交速度 >> 线程池处理速度

3、修复

调大了阻塞队列的长度:

private final ExecutorService pool = new ThreadPoolExecutor(16,32,10,TimeUnit.SECONDS,// groupInfos.size < 500, 这里取length * 1.5new LinkedBlockingQueue<>(700),new ThreadFactoryBuilder().setNameFormat("InspectionService-%d").build(),new ThreadPoolExecutor.AbortPolicy()
);

4、线程池使用的一点思考

  • 线程池自己定义,JDK中静态方法创建的阻塞队列长度为Long.MAX_VALUE,风险很高
参数设置要点示例
corePoolSizeCPU密集型:N+1(N=CPU核数)IO密集型:2N8核服务器:CPU密集型设9,IO密集型设16
maximumPoolSize不超过系统最大线程数(cat /proc/sys/kernel/threads-max)通常设置 coreSize 的 2-4 倍
blockQueue有界队列!无界队列=内存炸弹new LinkedBlockingQueue<>(200)
keepAliveTime线程空闲回收时间(建议30-60秒)TimeUnit.SECONDS + 10
  • 线程池中的线程带名字,不要用默认的pool-xxx,出现问题不好定位是哪儿的任务
  • 可以加必要监控,采集日志分析,到达阈值时告警处理
// 定时采集关键指标(每30秒)
// 单例调度线程池ScheduledExecutorService monitor = Executors.newSingleThreadScheduledExecutor();monitor.scheduleAtFixedRate(() -> {if (pool instanceof ThreadPoolExecutor executor) {int activeCount = executor.getActiveCount();int queueSize = executor.getQueue().size();long completedTaskCount = executor.getCompletedTaskCount();log.info("线程池状态:活跃线程:{} 队列堆积:{} 完成数:{}", activeCount, queueSize, completedTaskCount);if (queueSize > 500) {log.warn("线程池队列堆积过多,队列堆积:{} 完成数:{}", queueSize, completedTaskCount);}}}, 0, 30, TimeUnit.SECONDS);}

在这里插入图片描述

  • 核心业务与非核心业务使用独立线程池,做到资源隔离
http://www.lqws.cn/news/106453.html

相关文章:

  • Excel表格批量下载 CyberWin Excel Doenlaoder 智能编程-——玄武芯辰
  • 【办公类-48-04】202506每月电子屏台账汇总成docx-5(问卷星下载5月范围内容,自动获取excel文件名,并转移处理)
  • 2025 Java面试大全技术文章(面试题2)
  • java-springboot文件上传校验之只允许上传excel文件,且检查不能是脚本或者有害文件或可行性文件
  • Python+requests+pytest+allure自动化测试框架
  • 【知识点】第4章:程序控制结构
  • 互联网大厂Java求职面试:AI大模型与云原生技术的深度融合
  • js-day7
  • Blinko智能笔记系统实现跨平台同步与隐私保护的完整技术方案解析
  • Linux-GCC、makefile、GDB
  • 【软考】计算机系统构成及硬件基础知识
  • docker中组合这几个命令来排查 import 模块失败 的问题
  • Nginx实战
  • 各个主要目录的功能 / Linux 常见指令
  • 词语翻译的三步法与背后的语言学思维
  • 技巧小结:外部总线访问FPGA寄存器
  • 【25.06】fabric进行caliper测试加环境部署
  • 嵌入式系统:从技术原理到未来趋势(驱动程序篇)
  • 预览pdf(url格式和blob格式)
  • Python Day42
  • xmake的简易学习
  • 一、无参数的函数调用- RSP,EAX寄存器,全局变量,INT类型和MOV,INC,SHL指令
  • Python中os模块详解
  • Spring Boot 自动配置原理:从入门到精通
  • webstrom中git插件勾选提交部分文件时却出现提交全部问题怎么解决
  • UGUI Text/TextMeshPro字体组件
  • Activity
  • 6.3本日总结
  • agent mode 代理模式,整体要求,系统要求, 系统指令
  • ABP-Book Store Application中文讲解 - Part 7: Authors: Database Integration