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

 更新时间:2023年09月25日 09:41:29   作者:蚂蚁舞  
项目开发中经常需要执行一些定时任务,本文主要介绍了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>

启动类

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!" );
    }
}

必须加上这个注解 @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));
    }
}

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

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

比如我每秒钟执行一次

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

那是因为年(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 = "* * * * * ?")
@Scheduled(cron = "0/1 * * * * ?")

myw

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

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

myw

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

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

测试可以看到是闭区间的

myw

4.从0秒开始每隔10s触发一次

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

myw

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

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

myw

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

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

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

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 * * * * ?")
@Scheduled(cron = "0 0/1 * * * ?")

myw

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

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

myw

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

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

myw

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

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

myw

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

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

这里和分钟同样的问题 执行实际上是 每小时5分那个点和45分那个点执行 那就是说1个小时内执行两次 5分到45分 间隔40分钟,45分到下一个5分间隔20分钟,这里得注意并不是每隔40分钟。

myw

6.在20-40分钟闭区间内每隔3分钟执行一次,这种是两种符号的一起用

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

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 * * * ?")
@Scheduled(cron = "0 0 0/1 * * ?")

myw

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

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

myw

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

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

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

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

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

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

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

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

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

日期(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 * ?")
@Scheduled(cron = "0 0 0 * * ?")

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

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

3.2-20日每天执行一次

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

4.10-25日每隔三天执行

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

月份(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-JAN2月-2-FEB3月-3-MAR4月-4-APR5月-5-MAY6月-6-JUN7月-7-JUL8月-8-AUG9月-9-SEP10月-10-OCT11月-11-NOV12月-12-DEC

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

1.每月执行一次

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

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

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

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

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

其他的遇到再记录

星期(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")
@Scheduled(cron = "0 0 0 ? * 3")

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

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

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

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

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

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

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

年(7)的案例

myw

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

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

到此这篇关于SpringBoot+@EnableScheduling使用定时器的常见案例的文章就介绍到这了,更多相关SpringBoot+@EnableScheduling定时器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解Java中的防抖和节流

    详解Java中的防抖和节流

    防抖是将多次执行变为指定时间内不在触发之后,执行一次。节流是将多次执行变为指定时间不论触发多少次,时间一到就执行一次。这篇文章来和大家聊聊Java中的防抖和节流,感兴趣的可以了解一下
    2022-08-08
  • Java设计模式之观察者模式_动力节点Java学院整理

    Java设计模式之观察者模式_动力节点Java学院整理

    这篇文章给大家介绍流量java设计模式之观察者模式,定义对象间一种一对多的依赖关系,使得当每一个对象改变状态。下面通过类图和实例代码给大家介绍java设计模式之观察者模式,感兴趣的朋友一起看看吧
    2017-08-08
  • Java基础 Servlet监听器详解

    Java基础 Servlet监听器详解

    这篇文章主要介绍了Java基础 Servlet监听器详解的相关资料,需要的朋友可以参考下
    2017-07-07
  • SpringBoot中使用JeecgBoot的Autopoi导出Excel的方法步骤

    SpringBoot中使用JeecgBoot的Autopoi导出Excel的方法步骤

    这篇文章主要介绍了SpringBoot中使用JeecgBoot的Autopoi导出Excel的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • Java多线程教程之如何利用Future实现携带结果的任务

    Java多线程教程之如何利用Future实现携带结果的任务

    Callable与Future两功能是Java 5版本中加入的,这篇文章主要给大家介绍了关于Java多线程教程之如何利用Future实现携带结果任务的相关资料,需要的朋友可以参考下
    2021-12-12
  • Java中方法优先调用可选参数还是固定参数

    Java中方法优先调用可选参数还是固定参数

    这篇文章主要介绍了Java中方法优先调用可选参数还是固定参数,可选参数是 JDK 5 中新增的特性,也叫变长参数或可变参数,固定参数的概念恰好与可选参数相反,固定参数也就是普通的参,下文更多详细内容需要的小伙伴可以参考一下
    2022-05-05
  • Springboot3整合Mybatis3的完整步骤记录

    Springboot3整合Mybatis3的完整步骤记录

    这篇文章主要给大家介绍了关于Springboot3整合Mybatis3的完整步骤,Spring Boot和MyBatis分别是两个功能强大的框架,它们的协同使用可以极大地简化数据访问层的开发,提高整体的开发效率,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-01-01
  • Java微服务分布式调度Elastic-job环境搭建及配置

    Java微服务分布式调度Elastic-job环境搭建及配置

    Elastic-Job在配置中提供了JobEventConfiguration,支持数据库方式配置,会在数据库中自动创建JOB_EXECUTION_LOG和JOB_STATUS_TRACE_LOG两张表以及若干索引,来记录作业的相关信息
    2023-02-02
  • 图解Java经典算法冒泡排序的原理与实现

    图解Java经典算法冒泡排序的原理与实现

    冒泡排序是一种简单的排序算法,它也是一种稳定排序算法。其实现原理是重复扫描待排序序列,并比较每一对相邻的元素,当该对元素顺序不正确时进行交换。一直重复这个过程,直到没有任何两个相邻元素可以交换,就表明完成了排序
    2022-09-09
  • Java对字符串进行加密解密

    Java对字符串进行加密解密

    这篇文章主要为大家详细介绍了Java字符串加密解密,对用户输入的每个字符的值进行加密解密,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06

最新评论