You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot定时任务每日12点持续运行而非单次执行问题排查

解决Spring Boot定时任务每日12点频繁触发的问题

嘿,这种情况我碰到过好几次,大概率是你的Cron表达式写错了,但也不排除其他小问题,咱们一步步排查:

一、先检查你的Cron表达式(最常见的坑)

Spring Boot里的Cron表达式格式是 秒 分 时 日 月 周 [年],顺序可不能乱。

你可能踩的错误写法:

  • 如果你的表达式是 * * 12 * * ?:这会让任务在12点整的每一秒都执行一次,整小时内肯定疯狂触发
  • 如果是 0 * 12 * * ?:这表示12点的每一分钟的第0秒执行,也就是每分钟跑一次
  • 还有可能搞混了时和分的位置,或者误用了通配符,比如把日位的*写成了?但逻辑不对

正确的每日12点整执行的表达式:

0 0 12 * * ?

给你拆解下:

  • 0:秒位,指定第0秒执行
  • 0:分位,指定第0分执行
  • 12:时位,锁定12点整
  • *:日位,每天都执行
  • *:月位,每个月都执行
  • ?:周位,不指定(避免日和周的规则冲突,这是Spring Cron的最佳实践)

二、如果Cron没问题,排查其他可能性

1. 多实例部署导致重复触发

如果你的应用跑了多个实例,默认情况下Spring的@Scheduled定时任务会在每个实例上独立执行。这种情况得做分布式调度协调:

  • 用Redis分布式锁,任务执行前先抢锁,只有拿到锁的实例才执行任务
  • 改用Quartz并配置集群模式,或者用Spring Cloud Task这类专门的任务调度组件

2. 代码逻辑里的“假重复”

检查你的定时任务方法内部,有没有不小心写了循环逻辑,比如:

@Scheduled(cron = "0 0 12 * * ?")
public void dailyTask() {
    // 错误示例:一次任务里循环执行60次,看起来像每分钟一次
    for (int i = 0; i < 60; i++) {
        doBusinessLogic();
        try {
            Thread.sleep(60000); // 还睡了一分钟,完全误导
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

这种情况日志会显示多次执行,但其实是一次定时任务调用里的循环,不是定时任务重复触发。

3. 日志打印的误导

有时候日志的时间戳或者配置会让你产生错觉:

  • 检查日志的时区是否和服务器一致,比如本地日志用了UTC,服务器是北京时间,导致时间显示混乱
  • 看日志的线程ID,如果每次“触发”的线程ID相同,那大概率是一次任务里的多次操作;如果线程ID不同,才是真的多次触发

三、快速验证方法

可以先把Cron改成0 0/5 * * * ?(每5分钟执行一次),观察是否每5分钟只跑一次。如果这个测试正常,那改回0 0 12 * * ?肯定就没问题了。

内容的提问来源于stack exchange,提问作者smeeb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:18:21