发布时 kill 进程,服务要 60 多秒才真正退出,日志里还能看到定时任务在打点,运维只能再补一次 kill -9。碰到这种情况,我一般先确认改动有没有真的生效。

原因不复杂,newFixedThreadPool 建的是非守护线程,没有 shutdown 就一直是存活状态,JVM 要等所有非守护线程结束才退出。任务里还有循环拉取,自然退不出来。

「线程池未关闭」相关的验证我通常做两遍,改完一次、隔天再看一次,确认不是临时生效。改完顺手把文档补一句,省得下次自己重新推一遍。

Runtime.getRuntime().addShutdownHook(new Thread(() -> {
    pool.shutdown();
    pool.awaitTermination(10, TimeUnit.SECONDS);
}));

监控和日志的时间要对上,时区不一致会多绕很大一圈。临时改动用注释写上日期和原因,过两周自己都记不清为什么这么写。

具体做法是,在销毁钩子里先 shutdown 再 awaitTermination 给 10 秒宽限;超时还没结束就 shutdownNow 并记录未完成的任务;把长循环任务改成可中断 循环里检查中断标志;用 kill 而不是 kill -9 验证一次退出耗时。

最后用这个标准收尾,kill 后 3 秒内进程消失,日志里能看到线程池已关闭的记录。

作者 9823189