定时线程池失效问题引发的思考
最近在做的一个新功能,在结果探测的时候使用了定时线程池和普通线程池结合,定时线程池周期性创建子任务并往普通线程池提交任务。
问题:
在昨天测试老师发现,业务实际上已经成功了,但是页面还是一直显示进行中。
收到问题后,首先是去查看日志,确认下探测任务是否还在执行,结合日志和待探测任务的缓存数据发现,待探测任务队列是有数据的,但是探测任务一整天都没有执行了。那么可以初步确定问题是定时任务停止了,导致探测任务没有执行,所以业务虽然成功了,但是状态还是进行中。
因为之前遇到过定时线程池停止的问题,所以首先就怀疑是因为定时任务提交任务的时候,因为某种原因抛出了异常,导致定时线程池停止执行。如何验证呢?找遍了日志也没有找到相关的错误日志,于是通过arthas的trace方法监控该方法是否执行,经过了多个定时周期后,发现没有堆栈打印,说明定时线程池确实停止了执行,至此问题已经实锤。
没有日志,所以没法直接判断到底是什么异常导致的问题,分析代码和待探测任务队列发现,探测任务很多,达到了50个,但是我的线程池设置的参数如下(稍微了解线程池调度机制的应该都可以从参数设置上看出问题了):
个人初步分析:由于队列设置太小,任务太多,且大多数任务实际上非常耗时的(20s左右),且线程池提交的拒绝策略设置为了AbortPlicy,所以当线程池达到最大线程池数量以及队列满的情况下,新接收到提交的任务后,便会直接抛出异常,刚好这里没有异常捕获机制,导致了定时线程池的调度停止。
进一步的,我们需要结合代码逻辑看下需要增加哪些手段确保定时线程池不会因为异常停止,有以下几个手段:
1、兜底策略:增加捕获异常,防止定时线程池因为执行任务过程中抛出的异常导致停止
2、针对框架的策略:修改普通线程池的拒绝策略,使得在队列满和达到最大线程池数的情况下,提交任务也不会导致异常
3、针对业务上的策略:当前任务较多的原因是没有做业务校验,使得很多的不需要探测的数据进入了缓存,这里通过监听业务释放消息去掉部分数据
通过以上修改,替换到测试环境,观察问题暂时被解决了。但是观察到一个异常的现象,那就是发现任务执行的比较慢,感觉是在串行,没有达到想象中的并发执行。
于是每次提交任务时候,打印了线程池的activeCount、poolSize和queueSize三个数据,发现activeCount始终是1。那么问题就很明显了,说明线程池一直只有核心线程在执行,没有新开非核心线程。
到这里才恍然大悟,原来问题的根本在于线程池核心线程数的设置不对,导致任务一直往等待队列中堆积,等到队列满后,线程池扩容,但因为很多任务都是慢任务导致线程池处理速度小于任务提交速度,最终在线程和队列达到最高负荷时,再提交任务抛出异常,该异常导致了定时线程池停止。
该问题的核心还是对于线程池的参数设置以及线程池的执行流程理解不够,核心在于线程池的扩容机制:提交任务到线程池后,首先是放入等待队列,只有等待队列满了之后,才会创建非核心线程!!!
当达到最大线程(无空闲线程)以及队列满了之后,再提交任务时就会默认抛出中止异常(即AbortPolicy策略)。
总结:
1、使用定时线程池一定要使用try-catch语句,保证不会因为任务执行时候业务抛出异常,停止后续的任务
2、注意线程池的构造参数
1)一般来说核心线程数不要设置为1,因为我们使用线程池的目的一般有两个,一是让任务异步执行,二是让多个任务可以不并行执行。至于通过堆积任务排队执行实际上并不是大部分业务想要的特性。
那么如果把核心线程池设置为1,那么如果任务数量增加,但是没有达到队列上限,就会导致任务始终在排队执行,实际上就是串行,这和我们的目的相悖。
2)设置合理的任务等待队列长度,如果太长会导致无法触发非核心线程的创建,如果太短会导致经常触发线程池拒绝策略
3)如果担心核心线程过多,可以设置合适的线程销毁时间,并允许核心线程销毁
4)设置合理的提交拒绝策略,默认是中止策略(AbortPolicy),另外三种是主线程执行(CallerRunsPolicy)、丢弃策略(DiscardPolicy)、和丢弃最旧的任务策略(DiscardOldestPolicy)
推荐使用方法是使用中止策略,并在提交任务时增加try-catch语句,如果提交任务时报错,则打印提交失败的任务或丢到补偿机制的逻辑中。
5)特别是在使用定时线程池时,应该形成肌肉记忆和条件反射,首要注意点就是防止任务停止执行,所以一定要增加异常捕获机制
相关文章:

定时线程池失效问题引发的思考
最近在做的一个新功能,在结果探测的时候使用了定时线程池和普通线程池结合,定时线程池周期性创建子任务并往普通线程池提交任务。 问题: 在昨天测试老师发现,业务实际上已经成功了,但是页面还是一直显示进行中。 收到…...
Vue-ref 与 props
一、前言 在 Vue 的组件化开发中,父子组件之间的数据传递 是一个非常核心的需求。常见的场景包括: 父组件向子组件传递数据;子组件向父组件发送事件或数据;父组件直接调用子组件的方法或访问其属性。 Vue 提供了多种机制来实现…...

AXURE安装+汉化-Windows
安装网站:https://www.axure.com/release-history/rp9 Axure中文汉化包下载地址 链接:https://pan.baidu.com/s/1U62Azk8lkRPBqWAcrJMFew?pwd5418 提取码:5418 下载完成之后,crtlc lang文件夹 到下载的Axure路径下 双击点进这个目录里面。ctrlv把lan…...

ArcGIS Pro字段计算器与计算几何不可用,显示灰色
“字段计算器”不可用 如果计算字段命令不可用,请考虑以下可能性: 由 ArcGIS 管理的字段无法手动编辑。因此,无法计算 ObjectID(OID 或 FID)字段或地理数据库要素类的 Shape_Length 和 Shape_Area 字段的字段值。表中…...

mac电脑安装 nvm 报错如何解决
前言 已知:安装nvm成功;终端输入nvm -v 有版本返回 1. 启动全局配置环境变量失败 source ~/.zshrc~ 返回: source: no such file or directory: /Users/你的用户名/.zshrc~2 安装node失败 nvm install 16.13返回: mkdir: /U…...

第11节 Node.js 模块系统
为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统。 模块是Node.js 应用程序的基本组成部分,文件和模块是一一对应的。换言之,一个 Node.js 文件就是一个模块,这个文件可能是JavaScript 代码、JSON 或者编译过的…...

上海工作机会:Technical Writer Senior Technical Writer - 中微半导体设备
大名鼎鼎的中微半导体招聘文档工程师了,就是那家由中国半导体产业的领军人物尹志尧领导的、全员持股的公司。如果你还不了解他,赶快Deepseek一下“尹志尧”了解。 招聘职位:Technical Writer & Senior Technical Writer 公司名称&#…...
String 学习总结
1. 存储机制 短字符串优化(SSO, Small String Optimization) 现代标准库中的字符串实现普遍采用 SSO 技术,将长度较短(例如 ≤15 字节)的字符串数据直接存储在字符串对象内部的固定缓冲区(栈上)…...

Python微积分可视化:从导数到积分的交互式教学工具
Python微积分可视化:从导数到积分的交互式教学工具 一、引言 微积分是理解自然科学的基础,但抽象的导数、积分概念常让初学者感到困惑。本文基于Matplotlib开发一套微积分可视化工具,通过动态图像直观展示导数的几何意义、积分的近似计算及跨学科应用,帮助读者建立"数…...

Juce实现Table自定义
Juce实现Table自定义 一.总体展示概及概述 在项目中Juce中TableList往往无法满足用户需求,头部和背景及背景颜色设置以及在Cell中添加自定义按钮,所以需要自己实现自定义TabelList,该示例是展示实现自定义TableList,实现自定义标…...
【25.06】fabric进行caliper测试加环境部署
前置条件 安装一个Ubuntu20+的镜像 基础环境安装 Git cURL vim jq sudo apt install -y git curl vim jq Docker和Docker-compose 这个命令会自动安装docker sudo apt install docker-compose sudo chmod +x /usr/bin/docker-compose docker versiondocker-compose vers…...

【后端高阶面经:架构篇】51、搜索引擎架构与排序算法:面试关键知识点全解析
一、搜索引擎核心基石:倒排索引技术深度解析 (一)倒排索引的本质与构建流程 倒排索引(Inverted Index)是搜索引擎实现快速检索的核心数据结构,与传统数据库的正向索引(文档→关键词࿰…...

Windows应用-音视频捕获
下载“Windows应用-音视频捕获”项目 本应用可以同时捕获4个视频源和4个音频源,可以监视视频源图像,监听音频源;可以将视频源图像写入MP4文件,将音频源写入MP3或WAV文件;还可以录制系统播放的声音。本应用使用MFC对话框…...

【OCCT+ImGUI系列】012-Geom2d_AxisPlacement
Geom2d_AxisPlacement 教学笔记 一、类概述 Geom2d_AxisPlacement 表示二维几何空间中的一个坐标轴(轴系),由两部分组成: gp_Pnt2d:原点(Location)gp_Dir2d:单位方向向量ÿ…...
优化WP外贸建站提升用户体验
WordPress作为一个强大的建站工具,通过合理的优化,可以提升用户体验,吸引更多潜在客户。本文将为您介绍一些优化WordPress外贸建站的实用建议。 1. 响应式设计 随着移动设备的普及,确保您的WordPress网站具有响应式设计变得至关…...

【C++高并发内存池篇】性能卷王养成记:C++ 定长内存池,让内存分配快到飞起!
📝本篇摘要 在本篇将介绍C定长内存池的概念及实现问题,引入内存池技术,通过实现一个简单的定长内存池部分,体会奥妙所在,进而为之后实现整体的内存池做铺垫! 🏠欢迎拜访🏠ÿ…...

mac下通过anaconda安装Python
本次分享mac下通过anaconda安装Python、Jupyter Notebook、R。 anaconda安装 点击👉https://www.anaconda.com/download, 点击Mac系统安装包, 选择Mac芯片:苹果芯片 or intel芯片, 选择苹果芯片图形界面安装&#x…...
第3篇:数据库路由模块设计与 SQL 路由策略解析
3.1 什么是数据库路由? 在分库分表或多数据库实例架构中,**数据库路由模块(SQL Router)**的作用是: 将客户端发来的 SQL 请求路由到正确的后端数据库实例或分片表中执行。 它是数据库中间件的核心组件之一。 3.2 数据…...
ARINC818编解码设计FPGA实现
一、设计内容 1.基于xilinx平台进行系列产品设计 2.基于GT高速进行进行设计 3.提供良好的技术支持和售后服务 4.比较详细的代码注释 二、模块设计内容 1.模块顶层设计 2.编码模块部分设计 内容包括: 帧信息产生/ojbect0帧格式产生和发送/object2_object3帧格式产生…...

微软PowerBI考试 PL300-Power BI 入门
Power BI 入门 上篇更新了微软PowerBI考试 PL-300学习指南,今天分享PowerBI入门学习内容。 简介 Microsoft Power BI 是一个完整的报表解决方案,通过开发工具和联机平台提供数据准备、数据可视化、分发和管理。 Power BI 可以从使用单个数据源的简单…...
逻辑回归知识点
一、逻辑回归概念 逻辑回归(Logistic Regression)是一种广泛应用于分类问题的统计方法,尤其适用于二分类问题。 注意: 尽管名称中有"回归"二字,但它实际上是一种分类算法。 解决二分类的问题。 API:sklearn.linear_model.Logis…...
YARN架构解析:大数据资源管理核心
一、YARN的设计目标 解耦资源管理与作业调度:将资源管理(Resource Management)和任务执行(Task Execution)分离,提升集群资源利用率。支持多种计算框架:不再局限于MapRedu…...
嵌入式学习笔记 - freeRTOS在程序开始在任务内创建任务的好处是什么
在FreeRTOS中,程序启动后优先在初始任务(而非main()函数)内创建其他任务是一种常见且推荐的设计模式,其主要优势包括以下几点: 以下来自deepseek的回答,很全面很正确: 🔧 1. 避免…...

Ubuntu22.04 安装 CUDA12.8
1.下载CUDA 由于我装完 Ubuntu22.04 后就自动带了最新的显卡驱动,就没有再去配置驱动。 先查看驱动能支持的CUDA最高版本,这里显示可支持到12.8。 nvidia-smi在CUDA的 说明文档 可查看CUDA对应的驱动版本要求。 在 CUDA Toolkit Archive 查找需要的 …...

Android的uid~package~pid的关系
UID : Linux 系统级用户标识,Android 中每个应用安装时分配唯一 UID(如 1000)。 Package: Android 应用包名(例如android),一个 UID 可关联多个 Package(共享 UID 场景如android:sharedUserI…...
线段树刷题记录
一篇讲解很好的线段树博客:数据结构--线段树篇_数据结构线段树-CSDN博客 一、区间查询 无修改: (一)最值问题: 1.P1816 忠诚 - 洛谷 思路: 模板。 注意: 无。 代码: #include …...

20250530-C#知识:万物之父Object
C#知识:万物之父Object Object类(即object)是所有类的基类,这里面的方法还是需要好好了解一下。 1、Object类 是顶级父类,其他类默认都是Object类的子类(自定义类也会默认继承Object类)可以用O…...

多元素纳米颗粒:开启能源催化新纪元
在能源转型的浪潮中,纳米催化剂正成为推动能源技术突破的关键力量。多元素纳米颗粒(Polyelemental Nanoparticles)凭借其独特的元素协同效应,展现出在能源催化领域的巨大潜力。然而,合成这些复杂体系的纳米颗粒面临着诸…...

分布式锁优化:使用Lua脚本保证释放锁的原子性问题
分布式锁优化(二):使用Lua脚本保证释放锁的原子性问题 💻黑马视频链接:Lua脚本解决多条命令原子性问题 在上一章节视频实现了一个可用的Redis分布式锁,采用SET NX EX命令实现互斥和过期自动释放机制&…...

电脑wifi显示已禁用怎么点都无法启用
一、重启路由器与电脑 有时候,简单的重启可以解决很多小故障。试着先断开电源让路由器休息一会儿再接通;对于电脑,则可选择重启系统看看情况是否有改善。 二、检查驱动程序 无线网卡驱动程序的问题也是导致WiFi无法启用的常见原因之一。我…...