本文已参与「新人创作礼」活动,一起开启掘金创作之路。
spring boot 定时任务
定时任务在我们的系统中有着很重要的作用,对于那些没有实时性要求,并且需要周期性重复执行的任务来说,使用定时任务既可以解决。
业务场景
当我们在 12306 提交车票订单后不支付,返回订单页面,你会发现一个三十分钟的倒计时,三十分钟内未支付自动取消订单,车票将自动回到票池中,等待他人购买。
淘宝购物后,如果用户不主动确认收货的话,系统会在一段时间以后自动确认收货。
还有吃瓜群众最喜欢的微博热搜,也会定时去汇总热搜词条,更新热搜榜
在指定的时间,按照指定的频率(或执行次数)自动的执行指定的任务。
java 中的定时任务
单机
Timer:来自 JDK,从 JDK 1.3 开始引入。JDK 自带,不需要引入外部依赖,简单易用,当然功能相对单一
ScheduledExecutorService:同样来自 JDK,比 Timer 要晚一些,JDK 1.5 才引入,它的引入弥补了 Timer 的一些缺陷;
Spring Task:看名字就知道来自 Spring,Spring 环境中单机定时任务的不二之选。
分布式
Quartz:分布式定时任务的基石(其本身并不支持分布式任务调度)。功能丰富且强大,即能与简单的单体应用结合,又能支撑起复杂的分布式系统;
Elastic-job:来自当当网,基于 Quartz 开发,是一个具有完整定时任务处理流程,并且支持分布式的定时任务调度解决方案;
xxl-job:来自大众点评,同样也是基于 Quartz 开发,是一个轻量级的分布式任务调度平台。简单易用,国内使用很广泛。
另外,唯品会也有一个定时任务平台 ——Saturn,是对 Elastic-job 进行的二次开发。
通过上面的介绍,我们知道这些分布式的定时任务平台,都是基于 Quartz 的基础上进行的扩展。Quartz 算得上是 Java 定时任务届的标准了。
Spring Boot 整合定时任务
选择 Spring Task 与 Spring Boot 结合来实现一个定时任务的小实例。
在 Spring Boot 中使用定时任务,与使用其他技术一样,还是一如既往的简单方便。要开始定时任务功能,我们需要用到三个注解 ——@EnableScheduling、@Scheduled 和 @Component。
@EnableScheduling 用来开启定时任务功能,放在工程的主类上;@Scheduled 用来设定任务的执行规则,放在具体的定时任务方法上; @Component 我们已经很熟悉了,就是将类标记为一个被 Spring 管理的功能组件,放在包含有定时任务方法的类上。
Spring Task 有三种模式,分别是:fixedDelay、cron 和 fixedRate。话不多说,我们先看代码:
@Slf4j
@Component
public class TimeTask {
private int[] people = {9000,2000,3000,1000};
private int count = 0;
@Scheduled(fixedDelay = 5000)
public void fixedDelayTask() throws InterruptedException {
if (count < 4) {
int timeConsuming = people[count];
log.info("fixedDelayTask-----第 {} 个任务开始处理,耗时:{}ms",count+1, timeConsuming);
Thread.sleep(timeConsuming);
count++;
}
}
@Scheduled(cron = "0/5 * * * * ? ")
public void cronTask() throws InterruptedException {
if (count < 4) {
int timeConsuming = people[count];
log.info("cronTask-----第 {} 个任务开始处理,耗时:{}ms",count+1, timeConsuming);
Thread.sleep(timeConsuming);
count++;
}
}
@Scheduled(fixedRate = 5000)
public void fixedRateTask() throws InterruptedException {
if (count < 4) {
int timeConsuming = people[count];
log.info("fixedRateTask-----第 {} 个任务开始处理,耗时:{}ms",count+1, timeConsuming);
Thread.sleep(timeConsuming);
count++;
}
}
}
Cron 表达式
以上三种模式中,cron 模式最为灵活,可以应对更多的情况。下面简单介绍一下 cron 表达式,一个 cron 表达式总共有 7 个元素,分别如下:
时间单位 | 是否必填 | 取值范围 | 通配符 |
---|---|---|---|
秒 | 是 | 0-59 的整数 | , - * / 四个字符 |
分 | 是 | 0-59 的整数 | , - * / 四个字符 |
时 | 是 | 0-23 的整数 | , - * / 四个字符 |
日 | 是 | 1-31 的整数(需要考虑该月的具体天数) | ,- * ? / L W C 八个字符 |
月 | 是 | 1~12 的整数或者 JAN-DEC | , - * / 四个字符 |
周 | 是 | 1~7 的整数或者 SUN-SAT (1=SUN) | , - * ? / L C # 八个字符 |
年 | 否 | 1970~2099 | , - * / 四个字符 |
表达式的规则不需要刻意去记,需要的时候使用借助图形化工具生成即可 ——cron 生成器。
总结
这种单机版的定时任务适合简单的任务处理,当我们需要处理更多更复杂的任务时,就需要借助文章中提到的分布式定时任务调度。