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

线程池未争取关闭导致的一个bug

前提
自己写了一个任务执行器TaskStarter,在SpringBoot启动时自动执行一些初始化任务。使用数据库来保证一些幂等操作。
为了防止任务执行过久或者执行过程中失去响应,每个任务执行时都需要启动一个异步的任务来更新任务的RUN_TIME。
这个异步任务的执行由一个scheduledExecutor执行。
当任务执行失败时,应该在控制台打印错误并退出spring boot的启动。但现实情况是程序并未退出。

代码

任务执行器实现了ApplicationRunner接口,由SpringBoot在应用启动时调用run()方法执行业务逻辑。
并且构造函数中注册了jvm退出函数,在退出时关闭线程池。

@Component
@Slf4j
public class TaskStarter implements ApplicationRunner {protected ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(1);public TaskStarter() {this.threadPoolExecutor = new ThreadPoolExecutor(5,5,30,TimeUnit.SECONDS,new LinkedBlockingQueue<>(100),new ThreadFactory() {private final AtomicInteger integer = new AtomicInteger(1);@Overridepublic Thread newThread(Runnable r) {return new Thread(r, "taskRunner-" + integer.getAndIncrement());}});this.threadPoolExecutor.allowCoreThreadTimeOut(true);SpringApplication.getShutdownHandlers().add(() -> {//关闭线程池,忽略队列中的任务threadPoolExecutor.shutdownNow();scheduledExecutor.shutdownNow();});}
}

此处之2个细节:
1、通过Executors创建的线程池的线程都是非daemon的
2、导致jvm退出的几种情况:
正常关闭:当最后一个非守护线程结束或者调用了System.exit或者通过其他特定平台的方法关闭(发送SIGINT,SIGTERM信号等)
强制关闭:通过调用Runtime.halt方法或者是在操作系统中直接kill(发送SIGKILL信号)掉JVM进程
异常关闭:运行中遇到RuntimeException异常等。

在Spring Boot启动报错后,由于scheduledExecutor中的线程是非daemon导致jvm未退出。

解决方法
TaskStarter实现SmartLifecycle接口,并在stop()方法中调用线程池的shutdown方法,退出线程池。

http://www.hskmm.com/?act=detail&tid=10848

相关文章:

  • kafka创建topic
  • WPS 2025最新版EXE
  • OpenCV-图像通道提取与处理
  • Mac环境安装Nginx指南实录
  • csp2025
  • Ai元人文:价值共生时代的技术哲学构想之宣言
  • 完整教程:TruckSim与Matlab-Simulink联合仿真(一)
  • N皇后问题(DFS)
  • 2025csp初赛
  • PostGIS 介绍(2)--PostGIS 参考
  • Java编译全过程解密:从源码到机器码的奇幻之旅
  • 第一节计算机硬件基本组成
  • PyTorch深度学习实战【11】之神经网络的学习和训练 - 详解
  • 深搜广搜(DFS、BFS)
  • android studio发现设备立刻就掉
  • 见证语音领域 GPT-3 时刻!小米开源端到端语音模型 MiMo Audio;Xbox上线游戏助手,实时游戏理解+语音交互丨日报
  • go语言学习之基本数据类型转字符串
  • DeepLearning-LoRA 及其先进变体技术指南
  • 成功没有奇迹,只有积累----Bruce Lee
  • strtol() 函数 - 字符串转长整数(long int)
  • TypeScript学习
  • 对Transformer的个人理解
  • 第二节中央处理单元CPU知识点
  • day08 课程
  • 最小生成树MST-07 - jack
  • Java基础语法1
  • 不定高元素动画实现方案(上)
  • 实用指南:【鸿蒙面试题-6】LazyForEach 懒加载
  • 0voice-2.1.2-事件驱动reactor的原理与实现
  • Python 潮流周刊#120:新型 Python 类型检查器对比(摘要)