小易说IT 小易说IT

SpringBoot @Scheduled 示例代码

前置说明

  1. 开启定时任务:启动类加 @EnableScheduling(必加,否则 @Scheduled 不生效)

  2. 版本:SpringBoot 2.x/ 3.x 通用

  3. 注解参数 3 种:cron、fixedRate、fixedDelay


1. 启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling // 开启定时调度支持
public class ScheduleDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(ScheduleDemoApplication.class, args);
    }
}

2. 定时任务 Service 示例

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class ScheduleTaskService {

    /**
     * fixedRate:上一次任务【开始时间】算起,间隔多久执行
     * 每 5 秒执行一次
     */
    @Scheduled(fixedRate = 5000)
    public void taskFixedRate() {
        log.info("【fixedRate 任务】执行,时间:{}", System.currentTimeMillis());
    }

    /**
     * fixedDelay:上一次任务【执行完毕】后,间隔多久再执行
     * 任务跑完之后,等待 5s 再跑下一次(生产更常用)
     */
    @Scheduled(fixedDelay = 5000)
    public void taskFixedDelay() {
        log.info("【fixedDelay 任务】执行,时间:{}", System.currentTimeMillis());
    }

    /**
     * cron 表达式:灵活指定时间
     * 示例:每天凌晨 00:05 执行
     * cron 格式:秒 分 时 日 月 周
     */
    @Scheduled(cron = "0 5 0 * * ?")
    public void taskCronDaily() {
        log.info("【cron 每日凌晨00:05任务】执行");
    }

    /**
     * 每10秒执行一次 cron 写法
     */
    @Scheduled(cron = "0/10 * * * * ?")
    public void taskCronPer10s() {
        log.info("【cron 每10秒任务】执行");
    }

    /**
     * 支持从配置文件读取 cron(推荐,不用改代码重启)
     * application.yml: task.cron.report: 0 0 1 * * ?
     */
    @Scheduled(cron = "${task.cron.report}")
    public void taskCronFromConfig() {
        log.info("【配置文件cron任务】生成日报");
    }
}

3. yml 配置示例(读取外部 cron)

task:
  cron:
    report: 0 0 1 * * ?   # 每天凌晨1点

4. cron 简要说明

格式:秒 分 时 日 月 周

  • *:每一个

  • ?:不指定(日和周不能同时指定,一个写?)

  • 0 0 2 * * ? → 每天凌晨 2 点

  • 0 0/30 9-18 * * ? → 9 点到 18 点,每 30 分钟一次

在线 cron 工具:可以搜 cron 表达式生成器

5. ⚠️ 重要坑点(面试常问)

  1. 默认单线程:多个定时任务串行,某个任务阻塞会拖慢其他任务! 解决:自定义调度线程池

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

@Configuration
public class SchedulerConfig {
    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(8); // 线程数
        scheduler.setThreadNamePrefix("scheduled-task-");
        scheduler.setWaitForTasksToCompleteOnShutdown(true);
        return scheduler;
    }
}
  1. 单机任务!不支持分布式:多实例部署会重复执行;分布式要用 XXL-Job

  2. 没有内置失败重试、日志、告警、分片,适合简单小任务

  3. 任务逻辑里一定要 try-catch,异常抛出来会导致该定时任务后续不再调度

6. 补充:带 try-catch 健壮版模板

@Scheduled(fixedDelay = 5000)
public void safeTask() {
    try {
        // 业务逻辑
        log.info("定时业务执行");
    } catch (Exception e) {
        log.error("定时任务异常", e);
        // 这里可以发告警
    }
}

本文原创作者:易君召,详见:https://www.yijunzhao.cc/about,转载请注明出处。

原文链接 https://www.yijunzhao.cc/archives/springboot-scheduled-example-code

欢迎访问 https://www.yijunzhao.cc/

https://www.yijunzhao.cc/