文章目录
-
-
-
- 一、场景及背景描述
- 二、@Scheduled 注解调度器的实现
- 三、@Scheduled 注解任务调度详细说明
-
- 1、Cron 表达式的使用方式
- 2、fixedDelay & fixedDelayString 的使用方式
- 3、fixedRate & fixedRateString 的使用方式
- 4、initialDelay & initialDelayString 的使用方式
-
-
一、场景及背景描述
-
在项目开发过程中,我们经常需要执行具有固定周期性的任务,比如:会员到期提醒机制、手机话费停机提醒机制等。通过定时任务可以很好的帮助我们实现这些背景的功能。
-
常见几种定时任务比较:
定时任务框架 Cron 表达式 固定间隔执行 固定频率执行 任务持久化 开发难易度 JDK TimerTask 不支持 支持 支持 不支持 简单 Spring Schedule 支持 支持 支持 不支持 一般 Quartz 支持 支持 支持 支持 复杂 后续文章将会给出以上所有定时器的实现方式
二、@Scheduled 注解调度器的实现
-
添加
Spring Boot
依赖<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency> </dependencies>
-
应用主启动类添加
@EnableScheduling
注解/*** Copyright (C), 1998-2021, Shenzhen Rambo Technology Co., Ltd* Spring Boot Scheduled Sample 演示启动类** @author Rambo* @date 2021/02/19 17:06* @since 1.0.0.1*/ @SpringBootApplication @EnableScheduling public class SpringBootScheduleSampleApplication { public static void main(String[] args) { SpringApplication.run(SpringBootScheduleSampleApplication.class, args);} }
-
在需要实现调度任务的方法上添加
@Scheduled
注解并设置相应的调度周期即可 -
@Scheduled
注解所支持的参数参数属性 属性描述 cron cron表达式,指定任务在特定时间执行 fixedDelay 表示上一次任务执行完成后多久再次执行,参数类型为long,单位ms fixedDelayString 与fixedDelay含义一样,只是参数类型变为String fixedRate 表示按一定的频率执行任务,参数类型为long,单位ms fixedRateString 与fixedRate的含义一样,只是将参数类型变为String initialDelay 表示延迟多久再第一次执行任务,参数类型为long,单位ms initialDelayString 与initialDelay的含义一样,只是将参数类型变为String zone 时区,默认为当前时区,一般没有用到
三、@Scheduled 注解任务调度详细说明
1、Cron 表达式的使用方式
- 指定任务在特定时间执行
-
表达式定义规则
Cron
表达式由 6 或 7 个空格分隔的时间字段组成位置 时间域名 允许值 允许的特殊字符 1 秒钟 0~59 , - * / 2 分钟 0~59 , - * / 3 小时 0~23 , - * / 4 日期 1~31 , - * ? / L W C 5 月份 1~12 , - * / 6 星期 1~7 , - * ? / L C # 7 年(可选) 空值 1970~2099 , - * / -
常用表达式
表达式 功能描述 0/30 * * * * * 每30秒执行一次 0 0/5 * * * * 每5分钟执行一次 0 0 0 * * * 每天凌晨执行一次 0 0 9,12,18 * * * 每天9点、12点、18点整执行一次 0 30 3-5 * * * 每天 3~5点 30分执行一次 -
添加一个
cronTest
方法,并且设置每5秒执行一次,并且每次执行耗时10秒/*** 使用 @Scheduled 注解的前提:在启动类开启了 @EnableScheduling 注解** @author Rambo* @date 2021/2/20 09:55*/ @Scheduled(cron = "0/5 * * * * ?") public void cronTest() throws InterruptedException { log.info("-------------> 调度线程名称:[{}],被调度方法名称:[ScheduledTasks3.cronTest()],执行频率:5秒/次,每次执行耗时10秒,当前时间:[{}]", Thread.currentThread().getName(), DateUtil.now());// 模拟该任务响应时间较长,导致所有采用 @Scheduled 注解调度的定时任务都被阻塞TimeUnit.SECONDS.sleep(10); }
-
当方法执行时间超过任务调度频率,调度器会在(耗时 + 调度频率)后执行,即:第一次调度任务开始到任务结束以后(无论耗时多长)这一刻开始,再重新开始计时频率
2、fixedDelay & fixedDelayString 的使用方式
- 表示上一次任务执行完成后多久再次执行
-
添加一个
fixedDelayTest
方法,每隔5秒执行一次,每次耗时10秒// @Scheduled(fixedDelay = 1000*5) @Scheduled(fixedDelayString = "5000") public void fixedDelayTest() throws InterruptedException { log.info("-------------> 调度线程名称:[{}],被调度方法名称:[ScheduledTasks3.fixedDelayTest()],执行频率:5秒/次,每次执行耗时10秒,当前时间:[{}]", Thread.currentThread().getName(), DateUtil.now());// 模拟该任务响应时间较长,导致所有采用 @Scheduled 注解调度的定时任务都被阻塞TimeUnit.SECONDS.sleep(10); }
-
当执行频率小于执行耗时都场景,下一次调度的时间是 (耗时 + 调度频率)的时间
3、fixedRate & fixedRateString 的使用方式
- 表示按一定的频率执行任务
-
添加一个
fixedRateTest
方法,每隔5秒执行一次,每次耗时10秒// @Scheduled(fixedRate = 1000*5) @Scheduled(fixedRateString = "50000") public void fixedRateTest() throws InterruptedException { log.info("-------------> 调度线程名称:[{}],被调度方法名称:[ScheduledTasks3.fixedRateTest()],执行频率:5秒/次,每次执行耗时10秒,当前时间:[{}]", Thread.currentThread().getName(), DateUtil.now());// 模拟该任务响应时间较长,导致所有采用 @Scheduled 注解调度的定时任务都被阻塞TimeUnit.SECONDS.sleep(10); }
-
效果说明
-
如果执行频率大于执行耗时,则按照执行频率定时调度
-
如果执行频率小于执行耗时,则下一次执行调度会在执行耗时以后立刻执行
-
4、initialDelay & initialDelayString 的使用方式
- 表示延迟多久再第一次执行任务
-
添加一个
initialDelayTest
方法,每隔5秒执行一次,每次耗时10秒// @Scheduled(initialDelay = 10000, fixedDelay = 5000) @Scheduled(initialDelayString = "10000", fixedDelay = 5000) public void initialDelayTest() throws InterruptedException { log.info("-------------> 调度线程名称:[{}],被调度方法名称:[ScheduledTasks3.initialDelayTest()],首次运行等待10秒后执行调度任务,后续频率5秒/次,当前时间:[{}]", Thread.currentThread().getName(), DateUtil.now());// 模拟该任务响应时间较长,导致所有采用 @Scheduled 注解调度的定时任务都被阻塞TimeUnit.SECONDS.sleep(10); }
P.S
initialDelay
和initialDelayString
必须和非cron
表达式都其它两组组合使用 -
效果说明
initialDelay
和initialDelayString
必须和非cron
表达式都其它两组组合使用- 首次执行按照
initialDelay
和initialDelayString
预设值延迟后,后续所有频率按照其它组合都特性进行