当前位置: 代码网 > it编程>编程语言>Java > SpringBoot @Scheduled Cron表达式使用方式

SpringBoot @Scheduled Cron表达式使用方式

2025年03月24日 Java 我要评论
cron 表达式详解cron 表达式是用于定义定时任务执行时间的字符串,广泛应用于 spring 的 @scheduled、quartz 等定时任务框架。其核心是通过 ‌时间字段‌

cron 表达式详解

cron 表达式是用于定义定时任务执行时间的字符串,广泛应用于 spring 的 @scheduled、quartz 等定时任务框架。

其核心是通过 ‌时间字段‌ 和 ‌通配符‌ 组合实现复杂的调度规则。

1. 表达式格式‌

cron 表达式由 ‌6或7个字段‌ 组成,分别表示不同时间单位(spring 中通常用 ‌6位‌ 格式)。

格式如下:

字段允许值特殊字符说明
秒(seconds)0-59, - * /可精确到秒级调度
分(minutes)0-59, - * /
小时(hours)0-23, - * /
日(day)1-31, - * / ? l w月份中的某一天
月(month)1-12 或 jan-dec, - * /
周(week)0-7 或 sun-sat (0=周日), - * / ? l #周几(1=mon, 7=sun)
年(year)1970-2099 (可选), - * /‌spring 中通常省略

2. 特殊字符解析

符号作用示例
*匹配任意值0 * * * * ? 每分钟的0秒执行
?仅在 ‌日‌ 或 ‌周‌ 字段使用,表示“无意义”0 0 0 * * ? 每天0点执行
-范围区间0 0 10-12 * * ? 10-12点每小时执行
,多个值0 0 2,14 * * ? 每天2点和14点执行
/步长(间隔时间)0 0/5 * * * ? 每隔5分钟执行
l最后一天(仅 ‌日‌ 或 ‌周‌ 字段)0 0 l * * ? 每月最后一天0点执行
w最近工作日(仅 ‌日‌ 字段)0 0 0 15w * ? 每月15日最近的工作日执行
#指定月份的周几(仅 ‌周‌ 字段)0 0 0 ? * 6#3 每月第3个周五执行

3. 常用示例

表达式说明
0 0 12 * * ?每天中午12点执行
0 0/5 14 * * ?每天下午2点开始,每隔5分钟执行一次
0 15 10 ? * mon-fri每周一至周五上午10:15执行
0 0 0 1 1 ? 20242024年1月1日0点执行(需7位表达式)
0 0 8-18/2 ? * mon每周一上午8点到下午6点,每隔2小时执行一次
0 0 0 l * ?每月最后一天的0点执行
0 0 0 15w * ?每月15日最近的工作日执行
0 0 0 ? * 6#3每月第3个周五0点执行

‌4. 重点规则

‌1. 日与周的互斥性‌

  • 若同时指定 ‌日‌ 和 ‌周‌,需用 ? 忽略其中一个字段。
  • ✅ 正确:0 0 0 ? * mon(每周一执行,忽略日)
  • ❌ 错误:0 0 0 * * mon(日和周同时生效,可能冲突)

2‌. 月份和星期的缩写‌

  • 月份:jan, feb, mar… dec
  • 星期:sun, mon, tue… sat
  1. l 和 w 的组合‌
  • lw 表示当月的最后一个工作日。
  • l-3 表示倒数第3天。‌
  1. 年份字段(可选)‌
  • spring 的 @scheduled ‌不支持年份字段‌,需用6位表达式。

5. 动态与复杂场景‌

1‌. 动态 cron 表达式‌

  • spring 中可通过 @scheduled(cron = “${cron.expression}”) 从配置文件读取。
  • 结合数据库动态更新任务:
@scheduled(cron = "#{@cronservice.getcronexpression()}")
public void dynamictask() {
    // 业务逻辑
}

2‌. 避开整点任务高峰‌

  • 添加随机延迟(避免多个任务同时触发):
@scheduled(cron = "0 #{t(java.util.concurrent.threadlocalrandom).current().nextint(55)} * * * ?")
public void randomminutetask() {
    // 每小时随机分钟执行
}

3‌. 闰年处理‌

  • cron 无法直接处理闰年,需结合代码逻辑判断。

6. 调试与验证‌

1‌. 在线工具‌

  • crontab guru:快速验证表达式。
  • cronmaker:生成表达式并查看下次执行时间。
  1. 日志调试‌
  • 在任务方法中添加日志,观察触发时间是否符合预期:
@scheduled(cron = "0 0/5 * * * ?")
public void logtask() {
    log.info("任务执行时间: {}", localdatetime.now());
}

7. 常见问题‌

‌1. 为什么任务没有执行?‌

  • 检查是否添加 @enablescheduling
  • 检查 cron 表达式是否正确(如 spring 不支持年份字段)。
  • 检查时区设置(默认使用服务器时区,可通过 zone 属性修改)。

‌2. 如何实现每隔 n 天执行?‌

  • 方案1:使用 0 0 0 */n * ?(如 0 0 0 */5 * ? 每隔5天执行)。
  • 方案2:通过代码记录上一次执行时间。

‌3. 分布式环境下的幂等性‌

使用 redis 分布式锁:

@scheduled(cron = "0 0 * * * ?")
public void distributedtask() {
    if (redislock.trylock("tasklock", 10)) {
        try {
            // 业务逻辑
        } finally {
            redislock.unlock("tasklock");
        }
    }
}

总结‌

cron 表达式通过简洁的语法实现了灵活的定时规则,但需注意 ‌字段互斥性‌ 和 ‌特殊字符的适用场景‌。

在复杂业务中,可结合动态配置、分布式锁和日志监控来确保任务稳定执行。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com