【Spring】两步轻松实现定时任务
已完结
文章目录
- 【Spring】两步轻松实现定时任务
- 一、两步编码实现定时任务
-
- 1. 开启定时任务注解
- 2. 设置执行时间
- 3. cron表达式实现
- 二、cron表达式讲解
-
- 1. 在线生成Cron表达式工具
- 2. cron表达式结构
- 3. cron表达式通用符号
- 4. cron表达式专有符号
- 三、异步多线程实现
- 四、总结
一、两步编码实现定时任务
1. 开启定时任务注解
在启动类上添加注解:
@EnableScheduling
2. 设置执行时间
定义两个任务,分别设置执行时间,在方法上添加注解:
@Scheduled
代码:
package com.min.scheduler;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import java.text.DateFormat;
import java.util.Date;
@EnableScheduling
@SpringBootApplication
public class SchedulerApplication {
public static void main(String[] args) {
SpringApplication.run(SchedulerApplication.class, args);
}
@Scheduled(fixedRate = 5 * 1000) // 每5秒执行一次
public void playSth() {
System.out.println("好好学习 " + DateFormat.getDateTimeInstance().format(new Date()));
}
@Scheduled(fixedRate = 5 * 1000) // 每5秒执行一次
public void playSth2() {
System.out.println("天天向上 " + DateFormat.getDateTimeInstance().format(new Date()));
}
}
输出,可以看到两个任务每5秒执行一次。
3. cron表达式实现
前面通过注解
@Scheduled(fixedRate = 5 * 1000)
,其中fixedRate 属性实现了固定间隔时间完成定时任务输出,但是,如果想要在特定时间段内进行定时任务该怎么办呢?
cron表达式就很好地解决了这个问题,可应用于复杂的定时情况执行任务。
二、cron表达式讲解
1. 在线生成Cron表达式工具
在线Cron表达式生成器:https://cron.qqe2.com/
2. cron表达式结构
cron表达式结构可分为7个部分(用空格分隔),而Spring只支持6位解析,所以只定义6个部分。
3. cron表达式通用符号
通用符号:
, - * /
-
,
:表示列出枚举值。例如在Minutes域使用5,20,若定义@Scheduled(cron = "0 5,20 * * * ?")
,表示在时间的分钟数为5、20的时候触发事件。 -
-
:表示范围。例如在Minutes域使用5-20,若定义@Scheduled(cron = "0 5-20 * * * ?")
,表示在时间的分钟数为5-20的时候每分钟都触发事件。 -
*
:表示匹配该域的任意值。例如在Minutes域使用*,若定义@Scheduled(cron = "0 * * * * ?")
,表示在时间的分钟数上不做限制,每分钟都触发事件。 -
/
:表示起始时间开始触发,然后每隔固定时间触发一次。例如在Minutes域使用5/20,若定义@Scheduled(cron = "0 5/20 * * * ?")
,表示在时间的分钟数为5的时候触发一次,后每隔20分钟,即分钟数为25、45的时候分别再触发一次。
思考题
0 0 2 1 * ?
表示每年的1月里每天的2点钟(2:00:00)的时候都会触发事件
0 10,44 14 ? 3 WED
表示每年的3月里所有的星期三的14点钟的分钟数为10分钟和44分钟的时候都会触发事件
4. cron表达式专有符号
专有符号:
? L W LW # C
-
?
:只能用在DayofMonth和DayofWeek两个域,由于DayofMonth与DayofWeek互斥,须对其一设置? -
L
:表示最后,只能出现在DayofMonth和DayofWeek两个域。如果在DayofWeek域使用5L,意味着在最后的一个星期四触发事件。(提示:星期天是索引开始) -
W
:表示有效工作日(周一到周五),只能出现在DayofMonth域,系统将在离指定日期的最近的有效工作日触发事件。 -
LW
:这两个字符可以连用,表示在某个月最后一个工作日。 -
#
:用于确定每个月第几个星期几,只能出现在DayofWeek域。例如设置该域为4#2,表示某月的第二个星期三触发事件。 -
C
:只能用在DayofWeek和DayofMonth两个域,5C在日期域中就相当于日历5日以后的第一天,1C在星期域中相当于星期日后的第一天。
注意:专有符号中除
?
外,在Spring定时任务中都不支持!
三、异步多线程实现
上面通过两步编码实现了Spring定时任务,但是,默认是单线程的定时任务,如果任务持续时间较长,或者定时间隔时间较短,可能会将后续定时任务拖延,从而导致丢失任务。
异步多线程实现步骤:
- 开启异步注解
- 设置异步执行
为了看清楚是否进行异步执行,稍作修改代码,打印输出看结果。
@EnableScheduling
@EnableAsync
@SpringBootApplication
public class SchedulerApplication {
public static void main(String[] args) {
SpringApplication.run(SchedulerApplication.class, args);
}
//@Scheduled(cron = "0 0/30 9-22 * * ?") // 设置9点到22点,每隔30分钟执行一次
@Async
@Scheduled(fixedRate = 5 * 1000) // 每5秒执行一次(单位:毫秒)
public void playSth() {
System.out.println("线程:" + Thread.currentThread().getName() + "好好学习 " + DateFormat.getDateTimeInstance().format(new Date()));
}
// @Scheduled(cron = "0 0 9-22/4 * * ?") // 设置9点到22点,每隔4小时执行一次
@Async
@Scheduled(fixedRate = 5 * 1000) // 每5秒执行一次(单位:毫秒)
public void playSth2() {
System.out.println("线程:" + Thread.currentThread().getName() + "天天向上 " + DateFormat.getDateTimeInstance().format(new Date()));
}
}
输出可以明显看到是异步多线程执行结果。
四、总结
- 通过@EnableScheduling:开启定时任务(定义在启动类上)
- 通过@Scheduled:设置执行任务时间(定义在任务执行方法上)
- 通过@EnableAsync:开启异步执行(定义在启动类上)
- 通过@Async:设置异步执行(定义在异步执行方法上)
视频学习地址:https://www.bilibili.com/video/BV1xJ411G7ff