前置说明
开启定时任务:启动类加 @EnableScheduling(必加,否则 @Scheduled 不生效)
版本:SpringBoot 2.x/ 3.x 通用
注解参数 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. ⚠️ 重要坑点(面试常问)
默认单线程:多个定时任务串行,某个任务阻塞会拖慢其他任务! 解决:自定义调度线程池
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;
}
}
单机任务!不支持分布式:多实例部署会重复执行;分布式要用 XXL-Job
没有内置失败重试、日志、告警、分片,适合简单小任务
任务逻辑里一定要 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,转载请注明出处。
原文链接
欢迎访问