SpringTask
介绍:
- Spring Task 是Spring框架提供的任务调度工具,可以按照约定的时间自动执行某个代码逻辑。
- Spring3.0以后自主开发的定时任务工具,可以看做是一个轻量级的Quartz框架。使用起来很简单,除spring相关的包外不需要额外的包
- **定位:**定时任务框架
- **作用:**定时自动执行某段Java代码
为什么需要SpringTask:
- 信用卡每月还款提醒
- 银行贷款每月还款提醒
- 火车票售票系统处理未支付订单
- 入职纪念日为用户发送通知
- **强调:**只要是需要定时处理的场景都可以使用Spring Task
常见定时任务方案
-
实现定时任务的方案多种多样,其中用的较多的如下:
-
jdk的Timer和TimerTask:
- 可以实现简单的间隔执行任务,无法实现按日历去调度执行任务。
-
Quartz任务调度框架:
- Quartz是一个异步任务调度框架,功能丰富,可以实现按日历调度,这种开发中用的比较多,但是稍微复杂一点,不过功能非常强大。
-
Spring Task:
- Spring 3.0后提供Spring Task实现任务调度,支持按日历调度,相比Quartz功能稍简单,但是在开发基本够用,支持注解编程方式。如果Spring Task能够满足开发需求的话,尽量用Spring Task,毕竟是Spring全家桶中的一员,如果不能满足开发需求,这时候再考虑去使用Quartz框架。
cron表达式
-
在线Cron表达式生成器:https://cron.qqe2.com/
-
cron表达式其实就是一个字符串,通过cron表达式可以定义任务触发的时间
-
**构成规则:**分为6或7个域,由空格分隔开,每个域代表一个含义
每个域的含义分别为:秒、分钟、小时、日、月、周、年(可选)
-
举例:
2022年10月12日上午9点整 对应的cron表达式为:0 0 9 12 10 ? 2022
说明:一般日和周的值不同时设置,其中一个设置,另一个用?表示。
-
**比如:**描述2月份的最后一天,最后一天具体是几号呢?可能是28号,也有可能是29号,所以就不能写具体数字。
为了描述这些信息,提供一些特殊的字符。这些具体的细节,我们就不用自己去手写,可以使用在线cron表达式生成器
序号 说明 必填 允许填写的值 允许的通配符 1 秒 是 0-59 , - * / 2 分 是 0-59 , - * / 3 时 是 0-23 , - * / 4 日 是 1-31 , - * ? / L W 5 月 是 1-12 / JAN-DEC , - * / 6 周 是 1-7 or SUN-SAT , - * ? / L # 7 年 否 1970-2099 , - * / -
通配符说明:
*
表示所有值。 例如:在分的字段上设置 *,表示每一分钟都会触发。?
表示不指定值。使用的场景为不需要关心当前设置这个字段的值。例如:要在每月的10号触发一个操作,但不关心是周几,所以需要周位置的那个字段设置为”?” 具体设置为 0 0 0 10 * ?
-
表示区间。例如 在小时上设置 “10-12”,表示 10,11,12点都会触发。,
表示指定多个值,例如在周字段上设置 “MON,WED,FRI” 表示周一,周三和周五触发/
用于递增触发。如在秒上面设置”5/15” 表示从5秒开始,每增15秒触发(5,20,35,50)。 在月字段上设置’1/3’所示每月1号开始,每隔三天触发一次。L
表示最后的意思。在日字段设置上,表示当月的最后一天(依据当前月份,如果是二月还会依据是否是润年[leap]), 在周字段上表示星期六,相当于”7”或”SAT”。如果在”L”前加上数字,则表示该数据的最后一个。例如在周字段上设置”6L”这样的格式,则表示“本月最后一个星期五”W
表示离指定日期的最近那个工作日(周一至周五). 例如在日字段上置”15W”,表示离每月15号最近的那个工作日触发。如果15号正好是周六,则找最近的周五(14号)触发, 如果15号是周未,则找最近的下周一(16号)触发.如果15号正好在工作日(周一至周五),则就在该天触发。如果指定格式为 “1W”,它则表示每月1号往后最近的工作日触发。如果1号正是周六,则将在3号下周一触发。(注,”W”前只能设置具体的数字,不允许区间”-“)。#
序号(表示每月的第几个周几),例如在周字段上设置”6#3”表示在每月的第三个周六.注意如果指定”#5”,正好第五周没有周六,则不会触发该配置(用在母亲节和父亲节再合适不过了) ;小提示:’L’和 ‘W’可以一组合使用。如果在日字段上设置”LW”,则表示在本月的最后一个工作日触发;周字段的设置,若使用英文字母是不区分大小写的,即MON与mon相同。
基本使用:
- 首先,需要在启动类上加上注解@EnableScheduling
@EnableScheduling
public class ApiAutoConfiguration {}
- 当要创建一个定时任务时,@Scheduled可以直接注解在无返回值无参数方法上,表示该方法根据注解的规则定时执行。
- @Scheduled注解主要支持三种方式:
- 以下参数cron/fixedDelay/fixedRate三个属性必须且只能出现一个
- cron方式:@Scheduled(cron = "0 0 2 * * ? ")
- 固定速率:@Scheduled(initialDelay = 5000, fixedDelay = 2000),单位毫秒
- 固定延时:@Scheduled(initialDelay = 5000, fixedRate = 2000),单位毫秒
@Scheduled(cron = "0 0 2 * * ? ")
public void timerClean() {
}
线程池参数
- springboot对于spring-task默认是创建了一个线程数为1的线程池。
- 可以通过配置文件对线程参数进行调整。
spring:
task:
scheduling:
thread-name-prefix: scheduling-
pool:
size: 1
- 如果想更深度定制线程池,也可以自己实现TaskScheduler接口,并注册为Bean:
@Bean
public TaskScheduler taskScheduler() {
return new TaskSchedulerImpl();
}
调度效果
-
springboot内部是自动创建了一个ThreadPoolTaskScheduler对象,它实现了TaskScheduler接口,该类内部是使用了ScheduledExecutorService,因此任务调度的效果可参考ScheduledExecutorService文章。
-
不过经过了spring的封装,还是有部分与ScheduledExecutorService有区别。
-
区别1:@Scheduled注解方法执行时抛出异常,不会导致线程终止,不影响任务的下一次执行
spring-task对于任务执行,进行了统一的try catch,并设置了ErrorHandler进行错误日志打印。 -
区别2:Spring-Task扩展了对CRON的支持,其对任务耗时超过间隔时间的处理方式与固定延时相同