SpringBoot如何实现启动即执行、每小时间隔运行的Cron定时任务
SpringBoot 实现启动即执行、后续每小时间隔顺延的调度任务
纯靠静态@Scheduled(cron="xxx")实现不了这个需求:Cron是按固定日历时间点触发的,既做不到启动立刻执行,也没法自动对齐应用启动的时间点做间隔顺延。最贴合需求的实现方案如下:
实现步骤
- 第一步:开启Spring调度能力
在SpringBoot启动类上添加@EnableScheduling注解:
@SpringBootApplication @EnableScheduling public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
- 第二步:编写任务逻辑
用ApplicationRunner实现应用启动完成后立刻触发首次任务,再配合@Scheduled(fixedDelay = 3600000)实现「上一次任务执行完成后间隔1小时再跑下一次」的逻辑,加个轻量锁避免启动瞬间定时任务和启动触发的任务撞车重复执行:
import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.util.concurrent.locks.ReentrantLock; @Component public class HourlyTask implements ApplicationRunner { private final ReentrantLock lock = new ReentrantLock(); // 上次任务执行完成后,等待1小时(3600000毫秒)触发下一次 @Scheduled(fixedDelay = 3600000) public void scheduledTrigger() { runTask(); } // 应用启动完成后立即触发首次执行 @Override public void run(ApplicationArguments args) { runTask(); } private void runTask() { // 尝试获取锁,避免并发重复执行 if (lock.tryLock()) { try { // 替换成你的实际业务逻辑 System.out.println("任务执行时间戳:" + System.currentTimeMillis()); } finally { lock.unlock(); } } } }
方案说明
这个实现完全匹配给出的时间规则:
若应用上午9:10启动,首次任务9:10立即执行,后续依次在10:10、11:10、12:10顺延执行
fixedDelay的计时起点是上一次任务执行完成的时间点,哪怕某次任务执行耗时3分钟,下一次任务也会等它执行完之后再等1小时触发,不会出现Cron表达式到点就触发、不管上一次任务有没有跑完的问题。
避坑提醒
不要硬凑静态Cron表达式,比如写0 10 * * * ?只会在每小时的10分触发,如果应用9:20才启动,首次任务要等到10:10才会跑,完全不符合启动即执行的要求;如果写启动时动态生成Cron表达式的逻辑,复杂度远高于上面的方案,完全没必要。
内容的提问来源于stack exchange,提问作者Umang
相关产品推荐
相关产品推荐

