• SpringBoot+@EnableScheduling使用定时器的常见案例


    记录一下SpringBoot+@EnableScheduling使用定时器的常见案例

    我的SpringBoot版本

    <parent>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-parent</artifactId>
    	<version>2.0.5.RELEASE</version>
    	<relativePath/> <!-- lookup parent from repository -->
    </parent>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    启动类

    package boot.example.timer;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.scheduling.annotation.EnableScheduling;
    
    @SpringBootApplication
    @EnableScheduling
    public class App {
        public static void main( String[] args )
        {
        	SpringApplication.run(App.class, args);
            System.out.println( "Hello World!" );
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    必须加上这个注解 @EnableScheduling

    定时器TimerService

    package boot.example.timer.timer;
    
    import java.io.IOException;
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Service;
    
    @Service
    public class TimerService {
    
        @Scheduled(cron = "0/1 * * * * ?")
        public void timerTest() throws IOException {
        	long now = System.currentTimeMillis();
        	DateFormat format = new SimpleDateFormat("yyyy-MM-dd:HH:mm:ss");
            System.out.println("timer--"+format.format(now));
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    有很多的cron表达式来指定任务在需要的时间执行,可是有时候让人头疼,明明设置的cron是对的,可就是到点不执行,回过头来发现cron就是写错了,这很尴尬。

    cron表达式 秒钟(1) 分钟(2) 小时(3) 日期(4) 月份(5) 星期(6) 年(7) 长度是7 可为啥我们在程序里写的长度只有6呢?

    比如我每秒钟执行一次

    @Scheduled(cron = "0/1 * * * * * ?")  // SpringBoot运行报错
    
    • 1
    @Scheduled(cron = "0/1 * * * * ?")    // SpringBoot运行正常
    
    • 1

    那是因为年(7) 稍微特殊,他可以是空或者1970-2099 允许的字符有 , - * / 四种符号,实际没有(问号) ,可能是按照规律去推以为有问号而已。

    那么这个?问号到底是啥意思?
    ?问号字符只在日期(4)和星期(6)中使用,表示不确定的值 当需要的时候在使用,日期(4)和星期(6)是互相拉扯的,用?问号可以表示不想设置。

    秒(1)的案例

    myw
    1分钟有60秒 因此允许值范围是0-59
    符号*表示每秒
    符号,表示指定的秒数触发 比如 0,2,4,6 那么就在单位分钟内的 0 2 4 6那个点触发执行
    符号-表示指定范围区间 比如 20-40 那么就是在20到40s的区间内每秒执行
    符号/表示步进 比如 0/1 从0秒开始每秒触发 0/10 从0秒开始每隔10s触发一次

    1.1s执行一次

    @Scheduled(cron = "* * * * * ?")
    
    • 1
    @Scheduled(cron = "0/1 * * * * ?")
    
    • 1

    myw
    2.指定在 2s 17s 34s 52s 这四个秒钟点执行

    @Scheduled(cron = "2,17,34,52 * * * * ?")
    
    • 1

    myw
    3.指定在20 - 30s内每秒执行

    @Scheduled(cron = "20-30 * * * * ?")
    
    • 1

    测试可以看到是闭区间的
    myw
    4.从0秒开始每隔10s触发一次

    @Scheduled(cron = "0/10 * * * * ?")
    
    • 1

    myw
    5.从5秒开始每隔40s触发一次 注意这里!!!!

    @Scheduled(cron = "5/40 * * * * ?")
    
    • 1

    myw
    从运行的打印日志可以看到确实是从5s开始 40s后到了45秒执行了一次 可下一个40s就不是这么算的了 也就是说并不是每次间隔40s了,这里是20s 40s 如此的 相当于在5s执行了一次 45s执行了一次,原因嘛,反正就那样执行的。

    6.在5-40s闭区间内每隔2s执行一次,这种是两种符号的一起用

    @Scheduled(cron = "5-40/2 * * * * ?")
    
    • 1

    myw
    其他符号的组合?不尝试了,有空再说。

    分钟(2)的案例

    myw
    1小时有60分钟 因此允许值范围是0-59 和 秒一样的范围
    符号*表示每分钟
    符号,表示指定的分钟触发 比如 0,2,4,6 那么就在单位小时内的指定分钟数 0 2 4 6分那个点触发执行
    符号-表示指定范围区间 比如 20-40 那么就是在20到40分钟的点位区间内每分钟执行
    符号/表示步进 比如 0/1 从0分钟开始每分钟触发, 0/10 从0分钟开始每隔10分钟触发一次

    可以发现这些符号的意思很通用

    1.1分钟执行一次,此时秒的那一项设置为0

    @Scheduled(cron = "0 * * * * ?")
    
    • 1
    @Scheduled(cron = "0 0/1 * * * ?")
    
    • 1

    myw
    2.指定在 26 28 32 34 这四个分钟点执行

    @Scheduled(cron = "0 26,28,32,34 * * * ?")
    
    • 1

    myw

    3.指定在38 - 45闭区间这段分钟时间内每分钟执行

    @Scheduled(cron = "0 38-45 * * * ?")
    
    • 1

    myw

    4.从0分钟开始每隔2分钟触发一次

    @Scheduled(cron = "0 0/2 * * * ?")
    
    • 1

    myw

    5.从5分钟开始每隔40分钟触发一次(实际并不完全是40分钟)

    @Scheduled(cron = "0 5/40 * * * ?")
    
    • 1

    这里和分钟同样的问题 执行实际上是 每小时5分那个点和45分那个点执行 那就是说1个小时内执行两次 5分到45分 间隔40分钟,45分到下一个5分间隔20分钟,这里得注意并不是每隔40分钟。
    myw
    6.在20-40分钟闭区间内每隔3分钟执行一次,这种是两种符号的一起用

    @Scheduled(cron = "0 20-40/3 * * * ?")
    
    • 1

    myw

    其他的分钟相关的不尝试了。

    小时(3)的案例

    myw

    一天有24小时 因此允许值范围是0-23
    符号*表示每小时
    符号,表示指定的小时钟点触发 比如 1,6, 12, 19那么就在一天的 1 6 12 19点钟触发执行
    符号-表示指定范围区间 比如 8-20 那么就是在早8点到晚上8点每隔1个小时执行一次
    符号/表示步进 比如 0/1 从0时开始每小时触发 0/2 从0点钟开始每隔2小时触发一次,2/3 从2点钟开始每隔3小时执行一次

    1.每小时执行一次

    @Scheduled(cron = "0 0 * * * ?")
    
    • 1
    @Scheduled(cron = "0 0 0/1 * * ?")
    
    • 1

    myw

    2.在15点到17点之间每隔一小时执行一次

    @Scheduled(cron = "0 0 15-17 * * ?")
    
    • 1

    myw
    3.指定在 2点钟 10点钟 12点钟 18点钟 这四个小时点位执行

    @Scheduled(cron = "0 0 2,10,12,18 * * ?")
    
    • 1

    4.从0时开始每隔4小时触发一次

    @Scheduled(cron = "0 0 0/4 * * ?")
    
    • 1

    5.从2点钟开始每隔18小时触发一次 注意!!!!

    @Scheduled(cron = "0 0 2/18 * * ?")
    
    • 1

    这里没去测试了,等的时间太久了,2点钟执行一次 18小时候20点钟执行一下,下一个就超过了24小时,因此在第二天的2点钟执行一次,这样间隔是6小时 18小时,并不一定是每次间隔18小时的,得注意小时的范围是0-23。

    6.在2-18点钟闭区间内每隔3小时执行一次,这种是两种符号的一起用

    @Scheduled(cron = "0 0 2-18/3 * * ?")
    
    • 1

    日期(4)的案例

    myw
    一个月大概是30天 有31天的 因此允许值范围是1-31 如果说当月没有第31天 那么会抛出异常
    符号*表示每天
    符号,表示指定的天触发 比如 1,3, 5, 7那么就在当月的 第一天,第三天,第五天,第七天触发执行
    符号-表示指定范围区间 比如 2-20 那么就是在当月的第二天到第二十天之间每隔一天执行一次,闭区间内,第二天和第二十天也包含在内
    符号/表示步进 比如 2/3表示从第2天开始每隔3天执行一次,1/1表示从第一天开始每天执行一次
    符号?表示不确定的值,很少用到的
    符号L在这里表示当月的最后一天
    符号W表示指定离给定日期最近的工作日(周一到周五) 没用过
    符号C意思是Calendar,没用过

    这里写几个案例(未测试验证)

    1.每天执行一次

    @Scheduled(cron = "0 0 0 1/1 * ?")
    
    • 1
    @Scheduled(cron = "0 0 0 * * ?")
    
    • 1

    2.当月的1,3,5,7四天执行一次

    @Scheduled(cron = "0 0 0 1,3,5,7 * ?")
    
    • 1

    3.2-20日每天执行一次

    @Scheduled(cron = "0 0 0 2-20 * ?")
    
    • 1

    4.10-25日每隔三天执行

    @Scheduled(cron = "0 0 0 10-25/3 * ?")
    
    • 1

    月份(5)的案例

    myw
    一年有12个月 因此允许值范围是1-12,或者英文JAN-DEC
    符号*表示每个月
    符号,表示指定的月份触发 比如 1,6, 12那么就在1月 6月 12月触发执行
    符号-表示指定范围区间 比如 2-8 那么就是在2月到8月的闭区间内每月执行一次
    符号/表示步进 比如 1/1 从1月开始每隔一个月触发一次,2/3 从2月开始每隔3个月执行一次

    英文12个月份的缩写

    1月-1-JAN
    2月-2-FEB
    3月-3-MAR
    4月-4-APR
    5月-5-MAY
    6月-6-JUN
    7月-7-JUL
    8月-8-AUG
    9月-9-SEP
    10月-10-OCT
    11月-11-NOV
    12月-12-DEC

    这里写几个案例(未测试验证)

    1.每月执行一次

    @Scheduled(cron = "0 0 0 1 * ?")
    
    • 1
    @Scheduled(cron = "0 0 0 1 1/1 ?")
    
    • 1

    2.2月,4月,6月,8月执行一次

    @Scheduled(cron = "0 0 0 1 2,4,6,8 ?")
    
    • 1
    @Scheduled(cron = "0 0 0 1 FEB,APR,JUN,AUG ?")
    
    • 1

    3.2月-10月每隔三个月执行一次

    @Scheduled(cron = "0 0 0 1 2-10/3 ?")
    
    • 1
    @Scheduled(cron = "0 0 0 1 FEB-OCT/3 ?")
    
    • 1

    其他的遇到再记录

    星期(6)的案例

    myw
    一个星期有七天 因此允许值范围是1-7 当然也可以英文字母(SUN-SAT)
    符号*表示每个星期
    符号,表示指定的星期几触发
    符号-表示指定范围区间
    符号/表示步进
    符号L 当用在星期里的话表示星期的最后一天也就是星期六触发,在L前面加数字 比如2L 3L这种表示每个月的最后一个星期的星期几执行一次,有些难以理解,很多博客资料都这样说就这样定吧,测试的话花的时间太长,免了不去验证了!

    其他符号略过

    这里着重注意!!!!!
    星期的话 用英文字母 :星期天-SUN, 星期一-MON, 星期二-TUE, 星期三-WED, 星期四-THU,星期五-FRI,星期六-STA
    星期的话 用数字 是从星期一开始的,并不是星期天,这倒是有个坑在这里儿,也就是说 星期天-7,星期一-1,星期二-2,星期三-3,星期四-4,星期五-5,星期六-6

    我这里使用的是SpringBoot2.0.x做的测试
    可以证明至少在这个版本1-7指的是星期一到星期天
    myw
    可以查日历知道2023-07-19就是星期三 我写了一个执行的cron 星期三对应的就是3
    就是说1对应的不是星期天 而是星期一

    再看直接写WED 星期三
    myw
    所以建议使用字母方式

    这里写几个案例(未测试验证)

    1.每周星期三的零点零分零秒执行一次

    @Scheduled(cron = "0 0 0 ? * WED")
    
    • 1
    @Scheduled(cron = "0 0 0 ? * 3")
    
    • 1

    2.星期天,星期二,星期四零点零分零秒执行一次

    @Scheduled(cron = "0 0 0 ? * SUN,TUE,THU")
    
    • 1
    @Scheduled(cron = "0 0 0 ? * 7,2,4")
    
    • 1

    3.工作日每天零点零分零秒执行一次(星期一到星期五)

    @Scheduled(cron = "0 0 0 ? * MON-FRI")
    
    • 1
    @Scheduled(cron = "0 0 0 ? * 1-5")
    
    • 1

    4.星期一到星期天 每隔两天执行一次

    @Scheduled(cron = "0 0 0 ? * MON-STA/2")
    
    • 1
    @Scheduled(cron = "0 0 0 ? * 1-6/2")
    
    • 1

    其他单独关于星期的案例用到再补充

    年(7)的案例

    myw
    这个世界有多少年,都不知道,目前年份很少用到,要么留空,要么区间1970-2099年闭区间内
    符号*表示每年
    符号,表示指定的年触发 比如 2023,2025, 2030那么就在那年会触发执行
    符号-表示指定范围区间 比如 2023-2033 那么就是在2023年到2033年每年执行一次
    符号/表示步进 比如 2023/1 从2023年开始每年触发一次 2023/3 从2023年开始每隔3年执行一次

    按年的例子,没有用到过,随意尝试了几个,程序都报错,也不是刚需,于是不去折腾例子了,先按照符号表达的意思去理解,如果有问题在更改。

  • 相关阅读:
    51单片机3【单片机的种类】
    01程序执行原理
    简单中间件模型
    mybatis-plus根据指定条件批量更新
    前端html生成PDF
    (主从-阻抗)论文阅读笔记2
    高校/中职大数据实验室建设方案
    keil软件中按F12 无法跳转到函数、变量定义处
    关于Halcon中variation_model模型的快速解读。
    【无标题】
  • 原文地址:https://blog.csdn.net/myyhtw/article/details/131751863