一次触发线程池拒绝策略问题的排查

一次触发线程池拒绝策略问题的排查

这个问题的原因是团队中的同事排查出来的,本人觉得这个问题很经典,所以记录一下

线上偶尔会出现线程池拒绝策略触发的告警

每次出现告警都会查看数据库、JVM等监控,系统都是比较平稳的,没有出现请求暴涨的情况,所以认为大概率是线程池配置的问题

分析过程

线程池参数有很多,但最核心的是三个corePoolSize、maximumPoolSize、workQueuequeueCapacity,三者的关系如下

系统通过JDK原生线程池ThreadPoolTaskExecutor设置线程池参数,细细看了这个类的代码,corePoolSize、maxPoolSize、keepAliveSeconds等参数都是正常的设置(set),只有queueCapacity参数做了一些判断,代码如下

如果阻塞队列容量大于0,阻塞队列使用LinkedBlockingQueue,等于0,使用SynchronousQueue

于是做个测试,看看是不是这里导致的

测试代码如下,如果触发了线程池拒绝策略,打印出来

理论上核心线程数有10个,一组执行完,另一组还可以使用核心线程执行,是不需要触发非核心线程的,结果出乎我的意料

queueCapacity等于1的情况

queueCapacity等于0的情况

显然,使用LinkedBlockingQueue,线程复用率不高,导致触发了线程池拒绝策略

那么问题来了,为什么LinkedBlockingQueue线程复用率不高,google搜索了一下

千篇一律都是这种类型的文章,只有结论,没有说为什么,所以只能去看源码

线程池源码

线程池提交任务的代码如下

这段代码跟文章开头那张图是完美对应的,核心代码在于 workQueue.offer(command),因为入队失败,才会 addWorker(command, false)创建非核心线程

所以为什么SynchronousQueue会入队成功,LinkedBlockingQueue会入队失败,只能看两个队列的源码,比较一下,下面简单说说两者的源码

SynchronousQueue源码

SynchronousQueue代码还是蛮复杂的,有公平非公平两种模式,默认是非公平,如下图

  1. SynchronousQueue每个节点有三个状态,分别是未匹配的消费者、未匹配的生产者、正在匹配另一个生产者或消费者
  2. 当队列为空时,生产者或者消费者会直接进入栈中,自旋或者阻塞等待生产者或者消费者匹配
  3. 当栈中有生产者,消费者进入会去匹配该生产者,或者当栈中有消费者,生产者进入会进行匹配,匹配完成一起出栈
  4. 当栈中有生产者与消费者正在匹配,又进来了一个生产者或者消费者线程,它会协助两者匹配

看上是不是很懵,其实我一开始也很懵,juc包的代码是很难理解的,下面是详细的代码

LinkedBlockingQueue 源码解析

我的一点猜想

  1. LinkedBlockingQueue存取节点使用锁进行了互斥,性能没有SynchronousQueue好,所以同样的数据SynchronousQueue处理起来更快
  2. SynchronousQueue支持多线程协作栈中数据,可以充分利用多线程的好处,不像LinkedBlockingQueue,队列到达上限,直接返回false,任务只能创建非核心线程

由于本人水平有限,无法在多线程的环境下验证自己的猜想,期待大佬指点一二

参考文档

tech.meituan.com/2020/04/02/...

相关推荐
源代码•宸28 分钟前
大厂技术岗面试之谈薪资
经验分享·后端·面试·职场和发展·golang·大厂·职级水平的薪资
Anastasiozzzz37 分钟前
Java Lambda 揭秘:从匿名内部类到底层原理的深度解析
java·开发语言
骇客野人38 分钟前
通过脚本推送Docker镜像
java·docker·容器
铁蛋AI编程实战1 小时前
通义千问 3.5 Turbo GGUF 量化版本地部署教程:4G 显存即可运行,数据永不泄露
java·人工智能·python
晚霞的不甘1 小时前
CANN 编译器深度解析:UB、L1 与 Global Memory 的协同调度机制
java·后端·spring·架构·音视频
马猴烧酒.1 小时前
【面试八股|JVM虚拟机】JVM虚拟机常考面试题详解
jvm·面试·职场和发展
SunnyDays10111 小时前
使用 Java 冻结 Excel 行和列:完整指南
java·冻结excel行和列
摇滚侠1 小时前
在 SpringBoot 项目中,开发工具使用 IDEA,.idea 目录下的文件需要提交吗
java·spring boot·intellij-idea
云姜.1 小时前
java多态
java·开发语言·c++
李堇1 小时前
android滚动列表VerticalRollingTextView
android·java