目录
认识
能够让我们在指定的某个时间段自动执行任务,不需要自己去手动触发。
如:定时发送邮件、定时发送优惠卷等…
示例代码
文章中的代码,保存在Gitee中
定时任务 / 调度任务
开启调度
-
默认情况下不开启定时任务,如果想使用添加
@EnableScheduling
来显示启动@SpringBootApplication @EnableScheduling public class SpringSchedulerApplication { public static void main(String[] args) { SpringApplication.run(SpringSchedulerApplication.class, args); } }
-
更好的做法,是定义一个定时器的配置类,在结合
@ConditionalOnProperty
控制定时任务的开启和关闭@Configuration @EnableScheduling // 默认为false, 配置为true代表开启定时功能, @ConditionalOnProperty(name = "scheduler.enabled", matchIfMissing = true) public class SchedulerConfig { }
添加定时任务
默认单位都为毫秒(ms)
以固定延迟执行定时任务–fixedDelay
-
fixedDelay
属性配置定时任务在指定延迟时间后执行 -
新任务要等待前一个任务完成,示例如下:
@Scheduled(fixedDelay = 2000) public void computePrice() throws InterruptedException { log.info("current time: {}", LocalTime.now()); Thread.sleep(4000); }
-
每2秒执行一次
-
在新任务开启前, 需要等待旧任务完成。因此我们可以看到6秒后才会执行下一个任务
-
以固定速率执行定时任务–fixedRate
-
fixedRate
属性配置定时任务以固定时间执行定时任务,示例如下:@Scheduled(fixedRate = 3000) public void refreshPricingParameters() throws InterruptedException { log.info("current time: {}", LocalTime.now()); Thread.sleep(6000); }
-
在这里,我们通过设置
fixedRate
为3000毫秒,使refreshPricingParameters
方法每隔3秒就会执行一次。 -
但是由于
Scheduled
默认是单线程,导致打印时间为6秒间隔(Thread.sleep(6000))
。 -
如果想不被前一个任务的影响,可以通过下面两种方法解决:
-
通过开启异步任务
@Configuration @EnableScheduling @EnableAsync // 开启异步任务 @ConditionalOnProperty(name = "scheduler.enabled", matchIfMissing = true) public class SchedulerConfig { }
@Scheduled(fixedRate = 3000) @Async // 异步执行 public void refreshPricingParameters() throws InterruptedException { log.info("current time: {}", LocalTime.now()); Thread.sleep(6000); }
-
定时器默认不并行执行是因为线程池默认大小为1,可以通过配置**
spring.task.scheduling.pool.size
**调整线程池大小。
-
-
延迟第一次初始化–initialDelay
-
使用
fixedRate
和fixedDelay
属性,方法的第一次调用,会在上下文初始化完成后通过指定的时间进行调度。 -
但是可以通过
initialDelay
属性,指定第一次方法执行的延迟时间。示例如下:// 第一次延迟5秒后执行, 后续延迟都为3秒 @Scheduled(initialDelay = 5000, fixedRate = 3000) @Async public void refreshPricingParametersTemp() { log.info("current time: {}", LocalTime.now()); }
- 在这里,将方法第一次执行延迟时间设置为5秒
以 ISO 时间格式指定间隔–fixedRateString
-
可以通过这个文档ISO-文档了解ISO时间格式,示例如下:
@Scheduled(fixedDelayString = "PT02S") public void computePrice_TEMP() throws InterruptedException { log.info("current time: {}", LocalTime.now()); Thread.sleep(4000); }
- 在这里,设置
fixedDelayString
值为PT02S
,表示调用之间以 2 秒的固定延迟执行。
- 在这里,设置
-
除此之外,
fixedDelayString
还支持读取配置文件进行设置,示例如下:@Scheduled(fixedDelayString = "${interval}") public void computePriceTemp() throws InterruptedException { log.info("current time: {}", LocalTime.now()); Thread.sleep(4000); }
// yaml设置 interval: PT02S // properties设置 interval=PT02S
使用 Cron 表达式定义间隔
-
cron
表达式,用于设置更加复杂的时间。示例如下:@Scheduled(cron = "0/2 * * * * ?") public String computePrice() throws InterruptedException { log.info("current time: {}", LocalTime.now()); return ""; }
- 在这里,指定
cron
为0/2 * * * * ?
,表示每间隔2秒进行执行 - 注:
cron
支持读取配置文件
- 在这里,指定
-
cron
表达式格式,我们可以参考Spring官方的调度示例进行学习┌────────────── 秒 (0-59) │ ┌───────────── 分钟 (0 - 59) │ │ ┌───────────── 小时 (0 - 23) │ │ │ ┌───────────── 一个月中的某天 (1 - 31) │ │ │ │ ┌───────────── 月(1-12)(或JAN-DEC) │ │ │ │ │ ┌───────────── 星期几(0 - 7) │ │ │ │ │ │ (0 或 7 为星期日,或 MON-SUN) │ │ │ │ │ │ * * * * * *
结论
- Scheduler调度是核心模块,不需要添加其他依赖
- 默认情况下不开启调度,需要使用
@EnableScheduling
显示开启 - 结合
@ConditionalOnProperty
设置是否开启或禁用调度任务 - 被
@Scheduled
注解的方法,表示开启定时任务 fixedRate
或fixedDelay
设置执行间隔initialDelay
设置第一次方法执行的延迟时间
上述的代码示例都已上传到Gitee
参考文章: