记两个有关线程池的小问题

简介: 最近小伙伴们找我查的问题里,有两个与线程池相关的,最终都是花了一些时间才揪出原因所在,做一下记录。

最近小伙伴们找我查的问题里,有两个与线程池相关的,最终都是花了一些时间才揪出原因所在,做一下记录,供以后的自己和其它需要的人参考。

一、异步变同步

现象:

有一个方法,被请求后只是向线程池提交一个任务,然后马上返回,但从日志的 traceId 来看,偶现方法与任务在同一线程执行,接口耗时较长的情况。

分析过程:

这个其实就是一个知识点:当线程池里没有空闲线程,且任务队列已满时,会怎么处理新提交的任务?

可以看下 TheadPoolExecutor 类,这个类里面有几种预定义好的策略(implements RejectedExecutionHandler):

  • CallerRunsPolicy

  • AbortPolicy

  • DiscardPolicy

  • DiscardOldestPolicy

结合它们的名字以及注释就可以看到,它们分别对应:

  • 调度线程自己执行任务;(有一种例外情况是线程池被 shutdown 了则丢弃任务)

  • 忽略任务,并抛出异常;(默认值)

  • 丢弃任务,不产生异常;

  • 丢弃队列里最老的未被处理的任务,然后重新尝试调度新任务;(例外情况同一)

除此之外,还可以按需自己定义策略。

在我们的场景里,这个线程池使用的 RejectedExecutionHandler 是 CallerRunsPolicy,所以原因就找到了。

解决方案:

因为场景里主要的诉求是这个接口要快速返回,并且不能丢失任务,那这种情况使用消息队列会更加合适,所以将这里的向线程池提交任务,修改为向消息队列发送消息。

二、消失的任务

现象:

从日志可以看到,向线程池里提交了一个任务,找不到该任务执行的记录。

分析过程:

首先是怀疑这个任务被丢弃或者忽略了,经确认,该线程池的 RejectExecutionHandler 是使用的默认的 AbortPolicy,这样的话如果它被忽略,会有异常抛出,但日志里找不到异常记录。

那就是说,它成功进入了任务队列,但是没有被执行,哪里去了呢?

冥思苦想之后,怀疑是不是应用被杀掉了?查看 K8s 控制台里容器的滚动记录,果然在提交任务的时间点附近,应用发过版——破案。

解决方案:

提供两个思路:

  • 在保证任务执行逻辑幂等的前提下,通过消息队列、数据库记录任务状态+重试机制等方式调度任务;

  • 容器优雅下线,确认正在处理的请求和任务都完成后才能被 kill 掉。

目录
相关文章
|
程序员 数据库 开发者
值得收藏!如何快速画出一幅漂亮的架构图
这篇文章总结了常用的架构图类型,可以借鉴笔者提供的模板,快速地产出符合业务需要的架构图。
162498 95
|
安全 BI 数据安全/隐私保护
AD域、Windows AD域管理功能大全
Windows AD域管理功能大全,再也不用东拼西凑了!
1004 1
|
数据可视化 项目管理
职场低效重灾区,你踩中了几条?
在职场中,埋头苦干常被视为敬业,但未必高效。面对多任务和复杂项目,聪明的员工会选择合适的工具,如项目管理软件,将“埋头”转为“抬头”。通过任务分类、时间管理和复盘优化等技巧,提高工作效率,减少内耗,实现职业成长。
|
边缘计算 Kubernetes Cloud Native
恭喜我的同事黄玉奇入选开放原子开源基金会TOC
近日,开放原子开源基金会技术监督委员会(TOC)举行第 32 次例会。经过投票,阿里云云原生应用平台高级技术专家黄玉奇正式当选为开放原子开源基金会 TOC 成员。
恭喜我的同事黄玉奇入选开放原子开源基金会TOC
|
JSON JavaScript 前端开发
jQuery获取json文件的方法
jQuery获取json文件的方法
152 2
|
JavaScript Java 编译器
Java概述:跨足编程世界的瑞士军刀
Java概述:跨足编程世界的瑞士军刀
149 0
Java概述:跨足编程世界的瑞士军刀
|
JavaScript Java 测试技术
基于ssm+vue.js+uniapp小程序的旅游网站附带文章和源代码部署视频讲解等
基于ssm+vue.js+uniapp小程序的旅游网站附带文章和源代码部署视频讲解等
96 0
|
机器学习/深度学习
LCR 005. 最大单词长度乘积----位掩码的使用
LCR 005. 最大单词长度乘积----位掩码的使用
|
算法 C++
Acwing.51 数字排列(全排列)
Acwing.51 数字排列(全排列)
|
前端开发 JavaScript 定位技术
高德地图精确到某个位置
高德地图精确到某个位置
169 0