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

Spring Cron调度任务配置每59秒间隔执行出现重复触发问题咨询

问题原因分析

你的问题确实出在Cron表达式的配置上,咱们先拆解下*/59 * 9-21 * * *这个表达式的含义:
Cron表达式的结构是 秒 分 时 日 月 周,其中秒位的*/59表示「在秒的取值范围(0-59)内,每隔59秒触发一次」。

那具体怎么计算触发时间呢?

  • 第一个触发点是每分钟的0秒(因为0是秒范围的起始值)
  • 下一个触发点是0+59=59秒,刚好在当前分钟内
  • 但Cron的调度逻辑是基于字段独立周期判断的,*/59在秒位的本质是匹配所有满足秒数 % 59 == 0的时间点——0和59都符合这个条件(0%59=0,59%59=0),所以每分钟的0秒和59秒都会触发任务,这就是你日志里看到重复执行的核心原因。

更关键的是:Cron是基于固定时间点的调度,不管上一次任务是否执行完成,到了时间点就会触发,这和你想要的「以上一次任务结束时间为准,间隔59秒执行」的需求完全不匹配。

正确的解决方案

因为你的核心需求是「任务结束后间隔固定时间再执行」,同时限制在9-21点之间,Grails 4基于Spring框架,直接用@Scheduled的fixedDelay参数就能完美实现,不需要Cron表达式:

import org.springframework.scheduling.annotation.Scheduled;
import java.time.LocalTime;

// ...

@Scheduled(fixedDelay = 59000) // 59000毫秒 = 59秒,上一次任务结束后间隔59秒执行
public void schedule() {
    LocalTime now = LocalTime.now();
    // 判断当前时间是否在9:00-21:00之间
    if (now.isBefore(LocalTime.of(9, 0)) || now.isAfter(LocalTime.of(21, 0))) {
        return; // 不在时间范围内,直接返回不执行任务逻辑
    }
    try {
        log.info("Scheduler starts!");
    } catch (Exception e) {
        log.error("Error was caught in scheduler", e);
    }
}

这样配置后:

  1. 任务会在上一次执行结束后,等待59秒再启动下一次,完全符合你的「以上一次结束为准间隔59秒」的要求
  2. 通过代码判断当前时间,确保只有9-21点之间才会执行任务逻辑
  3. 不会出现Cron那种固定时间点重复触发的问题

如果你的任务执行时间可能超过59秒,fixedDelay依然会等任务结束后再开始计时,这比Cron的时间点调度更贴合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 12:03:12