认识cron表达式

概要

这篇文章介绍了 cron 的含义、cron 表达式语法和应用场景。

什么是 cron

cron 读作 “克龙”,是一种时间单位,1cron 等于百万年。在计算机世界中,cron 被用作定时任务,即在指定时间、周期自动执行预置的任务。cron 表达式广泛用于各种定时任务、调度服务。

Cron表达式语法规则

cron 表达式是一个字符串,有七个域,分别是秒、分、时、日、月、周、年,域的值可以是数字、特殊字符或两者的结合,域之间以空格分隔。

含义 数字范围 可用字符 备注
Seconds 0~59 ,-*/
Minutes 0~59 ,-*/
Hours 0~23 ,-*/
Day of Month 1~31 ,-*/?LWC
Month 1~12 ,-*/ 值也可填 JAN-DEC
Day of Week 周(星期) 1~7 ,-*/?LC# 也可填SUN-SAT,1 代表周日(SUN)
Year 1970~2099 ,-*/ 可选

注:

这个域是可选的,不限定年时,cron 表达式有 6 个域,分别是秒、分、时、日、月、周。

的取值范围在不同平台、不同语言中可能是不相同的,如在 linux 的 crontab 中,取值范围是 0~7,其中 07 都代表周日。

当域的值为数字时,表示在该时间时刻触发,如 0 0 8 * * ? * 表示在每天上午8点整触发。

特殊字符功能:

  • , 并列连接多个值,如 1,3,4 表示在 1、3 和 4 时触发。
  • - 表示范围,如 1-3 表示从 1 到 3,包括 1、2、3。
  • / 表示增量(步进),如 0/5 表示从 0 开始,每增加 5 触发一次。
  • * 表示所有值。
  • ? 用在 (Day of Month)和 (Day of Week)上,表示不限定值。日和周这两个域会相互影响,当指定了其中一个域,而另一个域不做限制时,另一个域要填 ? 。如想在每月 15 日早上 8 点整触发,不管是星期几都触发,则只能写成 0 0 8 15 * ? ,周的值只能是 ? ,而不能是 *个人理解:当指定了日为 15 后,如果同时指定周为 * ,表示周天到周六每天都触发,将导致限定条件冲突,最终日的限定条件失效,因而必须指定周为 ? 表示只关注日不需要关注周。
  • L 表示最后(Latest),只能用在 上,表示最后,如中单独使用 L 表示月的最后一天,中单独使用 L 表示一周的最后一天(SAT,周六);当 L 与数字连用时,日中的 3L 表示月的倒数第3天,3L 表示本月的最后一个星期二。
  • W 表示工作日(weekday),即周一到周五的任意一天,只能出现在 中,将在离指定日期最近的有效工作日触发。如 6W 表示将在距离 6 日最近的工作日触发,如果 6 日是工作日则在当日触发;如果 6 日是周六,则在周五触发;如果 6 日是周日,则在下周一触发。注意 W 的最近寻找不会跨过月份。
  • # 用于确定每个月的星期几,只能出现在 中,如 4#2 表示某月的第二个星期三。
  • LW 可以连用,表示某月的最后一个工作日。
  • C 表示和日历(Calendar)关联计算后的值,可用在 中,如日中的 5C 表示某月 5日后的第一天;周中的 5C 表示周四后的第一天。

示例

  • 0 0 8 * * ? * 每天早上 8 点触发
  • 0/5 * * * * ? 每 5 秒触发一次
  • 0 30 9,17 * * ? 每天上午9点半和下午17点半触发
  • 0 0 2 L * ? 每月最后一日的2点整触发
  • 0 0 7-22 * * ? 每天上午7点到晚上22点的整点触发
  • 0 0 14 ? * TUES,THUR,SAT 周二、周四、周六的下午14点整触发
  • 0 0 10 ? 5 1#2 每年5月的第二个星期日(母亲节)的上午十点整触发
  • 0 30 16 LW * ? 每月最后一个工作日的下午16点半出发

使用场景

Java Spring 项目

在使用 Spring 框架开发的 Java 项目中,可以很方便的创建定时执行任务,并使用 cron 表达式来指定执行策略。如以下代码将每 5 秒打印一句 Hi

1
2
3
4
5
6
7
8
9
10
11
12
13
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
@EnableScheduling
public class ScheduleService {

@Scheduled(cron = "0/5 * * * * ?")
private void sayHi(){
System.out.println("Hi");
}
}

代码说明:

  • @Component 注解用于将这个类标识为 Spring 组件,让 Spring 框架帮我们实例化和管理生命周期。
  • @EnableScheduling 注解用于告诉 Spring 开启定时执行功能。
  • @Scheduled(cron = "0/5 * * * * ?") 注解用于标识定时执行的方法,其中参数 cron 指定使用 cron 表达式作为触发条件,这里的 0/5 * * * * ? 表达式为 每 5 秒触发一次。

Java Cron 库

linux定时任务

在 linux 系统中,使用 crontab 来创建定时执行任务。

参考资料

总结

Cron 表达式用于创建定时器,表达式域包含 秒、分、时、日、月、周、年,域之间用空格分隔,一般年可省略。

要注意在不同平台、编程语言、定时任务框架中,Cron 表达式的规则可能不一样。