原创

CRON表达式

温馨提示:
本文最后更新于 2022年11月09日,已超过 905 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

一. 基本介绍

1. 描述

官网地址,cron表达式是由6个或7个字段组成的字符串,这些字段由空格分隔。字段可以包含任何允许的值,以及该字段允许的特殊字符的各种组合,使用方式为

* * * * ? *(代表启动时每一秒都执行一次),其中每个字段含义如下:

Field Name(字段名) Mandatory(是否必传) Allowed Values(允许值) Allowed Special Characters(特殊字符)
Seconds YES 0-59 , - * /
Minutes YES 0-59 , - * /
Hours YES 0-23 , - * /
Day of month YES 1-31 , - * ? / L W
Month YES 1-12 or JAN-DEC , - * /
Day of week YES 1-7 or SUN-SAT , - * ? / L #
Year NO empty, 1970-2099 , - * /

2. 特殊字符含义

特殊字符 含义 示例
* 所有可能的值。 在月域中,*表示每个月;在星期域中,*表示星期的每一天。
, 列出枚举值。 在分钟域中,5,20表示分别在5分钟和20分钟触发一次。
- 范围。 在分钟域中,5-20表示从5分钟到20分钟之间每隔一分钟触发一次。
/ 指定数值的增量。 在分钟域中,0/15表示从第0分钟开始,每15分钟。在分钟域中3/20表示从第3分钟开始,每20分钟。
? 不指定值,仅日期和星期域支持该字符。 当日期或星期域其中之一被指定了值以后,为了避免冲突,需要将另一个域的值设为?
L 单词Last的首字母,表示最后一天,仅日期和星期域支持该字符。说明 指定L字符时,避免指定列表或者范围,否则,会导致逻辑问题。 在日期域中,L表示某个月的最后一天。在星期域中,L表示一个星期的最后一天,也就是星期日(SUN)。如果在L前有具体的内容,例如,在星期域中的6L表示这个月的最后一个星期六。
W 除周末以外的有效工作日,在离指定日期的最近的有效工作日触发事件。W字符寻找最近有效工作日时不会跨过当前月份,连用字符LW时表示为指定月份的最后一个工作日。 在日期域中5W,如果5日是星期六,则将在最近的工作日星期五,即4日触发。如果5日是星期天,则将在最近的工作日星期一,即6日触发;如果5日在星期一到星期五中的一天,则就在5日触发。
# 确定每个月第几个星期几,仅星期域支持该字符。 在星期域中,4#2表示某月的第二个星期四。

3. 取值示例

示例 说明
0 15 10 ? * * 每天上午10:15执行任务
0 15 10 * * ? 每天上午10:15执行任务
0 0 12 * * ? 每天中午12:00执行任务
0 0 10,14,16 * * ? 每天上午10:00点、下午14:00以及下午16:00执行任务
0 0/30 9-17 * * ? 每天上午09:00到下午17:00时间段内每隔半小时执行任务
0 * 14 * * ? 每天下午14:00到下午14:59时间段内每隔1分钟执行任务
0 0-5 14 * * ? 每天下午14:00到下午14:05时间段内每隔1分钟执行任务
0 0/5 14 * * ? 每天下午14:00到下午14:55时间段内每隔5分钟执行任务
0 0/5 14,18 * * ? 每天下午14:00到下午14:55、下午18:00到下午18:55时间段内每隔5分钟执行任务
0 0 12 ? * WED 每个星期三中午12:00执行任务
0 15 10 15 * ? 每月15日上午10:15执行任务
0 15 10 L * ? 每月最后一日上午10:15执行任务
0 15 10 ? * 6L 每月最后一个星期六上午10:15执行任务
0 15 10 ? * 6#3 每月第三个星期六上午10:15执行任务
0 10,44 14 ? 3 WED 每年3月的每个星期三下午14:10和14:44执行任务
0 15 10 ? * * 2022 2022年每天上午10:15执行任务
0 15 10 ? * * * 每年每天上午10:15执行任务
0 0/5 14,18 * * ? 2022 2022年每天下午14:00到下午14:55、下午18:00到下午18:55时间段内每隔5分钟执行任务
0 15 10 ? * 6#3 2022,2023 2022年至2023年每月第三个星期六上午10:15执行任务
0 0/30 9-17 * * ? 2022-2025 2022年至2025年每天上午09:00到下午17:30时间段内每隔半小时执行任务
0 10,44 14 ? 3 WED 2022/2 从2022年开始,每隔两年3月的每个星期三下午14:10和14:44执行任务

二. springboot使用

1. 基本使用

如果不会写复杂的表达式,可以到cron在线网站根据自己的需求生成(百度CRON在线生成即可)

/**
 * @EnableScheduling 开启定时任务功能
 */
@Component
@EnableScheduling
public class ScheduledTask {
    //启动时,每秒都执行一次
    @Scheduled(cron = "* * * * * *")
    public void testScheduledTask(){
        System.out.println("定时任务");
    }

}

2.注意事项

  • spring只支持cron的6位参数,设置7为参数启动会报错

Encountered invalid @Scheduled method 'testScheduledTask': Cron expression must consist of 6 fields (found 7 in " *")

  • spring中对第六位参数的使用,1-7为周一到周日,和官方文档有些许差别

  • Scheduled定时任务默认是阻塞的,如果每秒执行一次业务 ,但是业务执行时间需要3秒,则该定时任务就会变为没4秒执行一次

    @Component
    @EnableScheduling
    @Slf4j
    public class ScheduledTask {
    
        @Scheduled(cron = "* * * * * *")
        public void testScheduledTask() throws InterruptedException {
            log.info("定时任务");
            TimeUnit.SECONDS.sleep(3);
        }
    }
    

​ 解决方案:

  1. 将业务代码采用异步执行的方式。

  2. 使用Scheduled任务的线程池(有些版本会失效),TaskSchedulingAutoConfiguration

    spring.task.scheduling.pool.size=10 #配置定时任务的线程池
    
  3. 开启异步任务

    @Component
    @EnableAsync//开启异步任务功能
    @EnableScheduling
    @Slf4j
    public class ScheduledTask {
    
        @Async//该方法异步执行
        @Scheduled(cron = "* * * * * *")
        public void testScheduledTask() throws InterruptedException {
            log.info("定时任务");
            TimeUnit.SECONDS.sleep(3);
        }
    }
    
正文到此结束