定时任务异常会导致线程终止、调度失效,必须在方法最外层用try-catch捕获Exception并记录完整堆栈,配合Spring errorHandler和监控告警构建双重保障。
Java定时任务运行中一旦抛出未捕获异常,默认会导致该任务线程终止,后续调度直接失效——这不是“重试”或“跳过”,而是彻底停止执行。所以异常处理不是锦上添花,而是必须做好的兜底动作。
Timer、ScheduledExecutorService 或 Spring @Scheduled 底层都依赖线程池或单线程调度器。当任务执行中抛出 RuntimeException(比如空指针、数据库连接超时),若没显式 try-catch,异常会向上冒泡到调度器的 run() 方法。而多数调度器(尤其是 JDK 原生实现)不会重新提交任务,也不会记录完整堆栈(日志可能被吞掉),表现就是“某天起任务不跑了”,排查困难。
在定时方法最外层用 try-catch 包住全部业务逻辑,是最直接有效的做法。不要指望全局异常处理器(如 @ControllerAdvice)能捕获定时任务异常——它只对 Web 层有效。
Spring 提供了更优雅的扩展点:实现 ScheduledTaskRegistrar 的 errorHandler,或配置 TaskScheduler 的 error handler。
光靠日志不够。线上环境必须建立可观测性:
基本上就这些。核心就一条:把定时任务当成生产环境里的“独苗线程”来敬畏,每个 run() 方法都得是防止单点崩溃的堡垒。