何亦冷

导航

统计

SpringBoot项目中@Async方法没有执行的问题分析

复制代码
现象: 
    1. 表面现象: 方法中输出的日志, 日志文件中找不到, 也没有任何报错(即@Async标注的方法没有执行, 也没有报错)
    2. 分析现象: 日志中某个时刻之后没有了task-xxx线程的日志
 
原因: 
    @Async异步方法默认使用Spring创建ThreadPoolTaskExecutor(参考TaskExecutionAutoConfiguration), 
其中默认核心线程数为8, 默认最大队列和默认最大线程数都是Integer.MAX_VALUE. 创建新线程的条件是队列填满时, 而
这样的配置队列永远不会填满, 如果有@Async注解标注的方法长期占用线程(比如HTTP长连接等待获取结果), 
在核心8个线程数占用满了之后, 新的调用就会进入队列, 外部表现为没有执行.

解决:
    手动配置相应属性即可. 比如
    spring.task.execution.pool.queueCapacity=4
    spring.task.execution.pool.coreSize=20

备注: 
    此处没有配置maxSize, 仍是默认的Integer.MAX_VALUE. 如果配置的话, 请考虑达到最大线程数时的处理策略(JUC包查找RejectedExecutionHandler的实现类)
    (默认为拒绝执行AbortPolicy, 即抛出异常)
    
    AbortPolicy: 直接抛出java.util.concurrent.RejectedExecutionException异常
    CallerRunsPolicy: 主线程直接执行该任务,执行完之后尝试添加下一个任务到线程池中,可以有效降低向线程池内添加任务的速度
    DiscardOldestPolicy: 抛弃旧的任务
    DiscardPolicy: 抛弃当前任务
    
截图:
    1. ThreadPoolTaskExecutor
    2. SpringMonitor的配置属性
    3. SpringMonitor的Threads
复制代码

 

 

 

 

 

posted on   何亦冷  阅读(6475)  评论(0编辑  收藏  举报

编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示