@scheduled没生效的主因是未添加@enablescheduling、方法不在spring容器bean中、或cron表达式格式错误(如位数不符、周字段取值错误)。

@Scheduled 注解为什么没生效?检查这三处
Spring 的 @Scheduled 不是加了就自动跑的,缺一个关键开关就会静默失效。
- 必须在启动类或配置类上加
@EnableScheduling,否则整个调度模块压根不加载 - 被注解的方法必须在 Spring 容器管理的 Bean 里(不能是 new 出来的对象)
- 方法必须是 public、无参数、返回 void;如果用了
@Async混搭,还要确认线程池是否配置正确
常见现象:控制台没报错,但方法一次都不执行——大概率是漏了 @EnableScheduling 或方法不在 Bean 中。
Cron 表达式写错导致任务不触发或乱跑
Cron 是最易出错的环节,Spring 用的是 quartz 风格(6 位或 7 位),不是 Linux crontab 那套。
- 6 位格式:
秒 分 时 日 月 周(如"0 0 * * * ?"表示每小时整点) - 第 6 位“周”用 1–7(1=周日,7=周六),
?表示不指定“日”或“周”中的某一个(二者必填其一) -
"0 0 12 * * ?"是每天中午 12 点,"0 0 12 ? * MON"是每周一中午 12 点(注意:不是* * * * * MON) - 别用
*过度覆盖,比如"0/5 * * * * ?"每 5 秒跑一次,可能压垮 DB 或接口
错误示例:"0 0 * * *"(少一位)、"0 0 * * * *"(多一位)、"0 0 * * * 1"(把周一写成 1,实际应为 2)——都会导致解析失败或语义偏差。
单机定时任务 vs 分布式场景下的陷阱
@Scheduled 天然是单机的。同一套代码部署到 3 台机器,任务就会执行 3 次。
- 如果业务不允许重复(比如发短信、扣库存),必须加分布式锁(如 RedisLock)或改用 XXL-JOB、ElasticJob 等调度平台
- 应用重启时,正在执行的任务不会被中断,但新周期会照常触发;若需防止重入,得自己加
synchronized或数据库 for update - 时间精度依赖 JVM 所在服务器时钟,跨机房部署时要注意 NTP 同步,否则 cron 触发时间可能漂移
简单项目先用 @Scheduled 没问题,但只要上了生产、有高可用或幂等要求,就得立刻考虑它是不是真适合你当前的部署形态。
真正难的不是写对 Cron 表达式,而是想清楚“这个任务到底该在哪台机器上、以什么频率、在什么状态前提下运行”。很多问题表面是配置错了,其实是调度边界没定义清楚。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











