🌟 Spring Task高能预警:你以为的Cron表达式可能都是错的!【附实战避坑指南】
开篇暴击:为什么你的定时任务总在凌晨3点翻车?
“明明设置了
0 0 2 * * ?
,为什么任务每天凌晨3点执行?” —— 来自某位头发渐稀的程序员真实呐喊
一、Spring Task极速入门(小白必看)
1.1 三行代码开启定时任务
java">@SpringBootApplication
@EnableScheduling // 魔法开关
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}@Component
public class ReportJob {// 每天9点执行(错误示例!后文揭晓原因)@Scheduled(cron = "0 0 9 * * ?")public void generateDailyReport() {// 你的报表生成逻辑}
}
二、Cron表达式深水区(90%的人都踩过这些坑)
2.1 Cron语法速查表(Spring特供版)
字段 | 秒 | 分 | 时 | 日 | 月 | 周 | 年(可选) |
---|---|---|---|---|---|---|---|
取值 | 0-59 | 0-59 | 0-23 | 1-31 | 1-12 | 1-7(1=周日) | 1970-2099 |
2.2 暴击灵魂的六连问
-
*
和?
到底有什么区别?*
表示任意值,?
表示不指定(仅用于日和周的互斥)
-
为什么
0 0 0 * * 1
不是周一执行?- Spring的周字段范围是1-7(1=周日),正确写法:
0 0 0 ? * 2
(周一)
- Spring的周字段范围是1-7(1=周日),正确写法:
-
如何实现每月最后一天执行?
- 使用Spring扩展语法:
0 0 0 L * ?
- 使用Spring扩展语法:
-
0/5
和*/5
有什么区别?- 没区别!都是每隔5单位执行(但建议统一用
0/5
)
- 没区别!都是每隔5单位执行(但建议统一用
-
如何避开周末执行?
java">@Scheduled(cron = "0 0 9 * * 2-6") // 周一到周五
-
为什么我的任务总是重复执行?
- 检查线程池配置:
spring.task.scheduling.pool.size=5
- 检查线程池配置:
三、高阶玩家专属技巧(同事看了直呼内行)
3.1 动态修改Cron表达式
java">@Autowired
private ThreadPoolTaskScheduler taskScheduler;// 动态调整报表生成时间为10:30
public void updateReportTime() {taskScheduler.schedule(this::generateDailyReport,new CronTrigger("0 30 10 * * ?"));
}
3.2 分布式环境下的死亡陷阱
单机定时任务在分布式环境重复执行
解决方案:
- 加Redis分布式锁
- 改用XXL-JOB等分布式调度框架
四、性能核弹级优化方案
4.1 线程池配置(application.yml)
spring:task:scheduling:thread-name-prefix: my-task- # 线程名前缀pool:size: 10 # 核心线程数shutdown:await-termination: true # 优雅关闭await-termination-period: 60s
4.2 监控任务执行时长(AOP实现)
java">@Aspect
@Component
public class TaskMonitorAspect {@Around("@annotation(org.springframework.scheduling.annotation.Scheduled)")public Object monitor(ProceedingJoinPoint pjp) throws Throwable {long start = System.currentTimeMillis();try {return pjp.proceed();} finally {long cost = System.currentTimeMillis() - start;log.info("任务 {} 执行耗时: {}ms", pjp.getSignature(), cost);}}
}
五、血泪总结:Cron表达式十大作死写法
错误写法 | 正确写法 | 翻车现象 |
---|---|---|
0 0 9 * * 1 | 0 0 9 ? * 2 | 周日执行而非周一 |
0 0 12 31 2 * | 0 0 12 L 2 ? | 2月31日不存在 |
0 */5 * * * * | 0 0/5 * * * * | 实际效果相同但易读性差 |
0 0 3 1-7 * 1 | 0 0 3 1-7 * 2 | 字段冲突导致意外触发 |
六、课后彩蛋:在线Cron生成工具推荐
https://cron.qqe2.com/
“好的定时任务应该是:老板不知道它的存在,但业务离不开它的运行。” —— 佚名