SpringBoot下的定时任务调度@Scheduled,Java原生定时任务
一、概述
定时任务调度,一句话概括就是:基于给定的时间点、给定的时间间隔、自动执行的任务(方法)。
二、java生态下的定时任务实现方式
-
Spring 3.0
以后自带了task
调度工具简单方便,(SpringBoot
项目里的主流实现方式)
-
java
自带的API
java.util.Timer
类 java.util.TimerTask
类 (早期的实现方式)
-
Quartz
开源框架,功能强大,但是使用起来稍显复杂。 (逐渐淘汰)
三、SpringBoot项目里的定时器主流实现方式
3.1 SpringBoot引导类了上加上@EnableScheduling
开启定时任务支持
@EnableScheduling //开启定时任务支持
public class Application {
public static void main(String[] args) {
SpringApplication.run(AdminServerApplication.class,args);
}
}
3.2 在引导类的包及其子包下编写定时任务类
@Component
public class ScheduledTask {
/**
* @Scheduled 表示这是一个需要定时执行的方法
* cron 表达式,用于设置每次执行的时间间隔
*/
@Scheduled( cron = "0/20 * * * * ? ") //配置时间规则:每20秒执行一次
public void scheduledMethod() throws ParseException {
//业务逻辑
System.out.println("定时任务执行");
}
}
3.3 Scheduled注解的各个参数解析
Scheduled
注解源码:
package org.springframework.scheduling.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {
String CRON_DISABLED = "-";
String cron() default "";
String zone() default "";
long fixedDelay() default -1L;
String fixedDelayString() default "";
long fixedRate() default -1L;
String fixedRateString() default "";
long initialDelay() default -1L;
String initialDelayString() default "";
-
zone
:时区设置,可以设置为java.util.TimeZone
中的zoneId
,该字段一般留空即可
-
fixedDelay
:执行完一次以后(方法完全执行完之后)隔多长的时间再去执行
//执行完一次以后隔10000毫秒,即10秒再去执行
@Scheduled(fixedDelay = 10000)
-
fixedDelayString
:与fixedDelay
不同的就是只接收字符串,并且可以支持SpringEL
表达式来赋值
//执行完一次以后隔10000毫秒,即10秒再去执行
@Scheduled(fixedDelayString = "10000")
//SpringEL的赋值方式
@Scheduled(fixedDelayString = "${Schedul.fixedDelay}")
SpringEL
的赋值方式 需要在application.yml
中配置
Schedul:
fixedDelay: 10000
-
fixedRate
: 在上一次开始执行时间点(也就是方法刚开始执行的时候)之后多长时间再执行
//在上一次开始执行时间点(也就是方法刚开始执行的时候)的10000毫秒后,即10秒后再去执行
@Scheduled(fixedRate = 10000)
-
fixedRateString
:与fixedRate
不同的就是只接收字符串,并且可以支持SpringEL
表达式来赋值
//在上一次开始执行时间点(也就是方法刚开始执行的时候)的10000毫秒后,即10秒后再去执行
@Scheduled(fixedRate = "10000")
-
initialDelay
:设置第一次执行时的等待时间,即等待多长时间,再去执行第一次
//第一次延迟2秒后执行,之后就按只有fixedRate参数的方式每10秒执行一次
@Scheduled(initialDelay=2000, fixedRate=10000)
//第一次延迟2秒后执行,之后按只有fixedDelayStrin参数的方式每10秒执行一次
@Scheduled(initialDelay=2000, fixedDelayString=10000)
相当于initialDelay
也就只对定时任务的首次执行有效
-
initialDelayString
:与initialDelay
不同的就是只接收字符串,并且可以支持SpringEL
表达式来赋值
-
cron
表达式:用于设置每次执行的时间间隔
名称 |
是否必须 |
允许值 |
可以使用的通配符 |
秒 |
是 |
0-59 |
, - * / |
分 |
是 |
0-59 |
, - * / |
时 |
是 |
0-23 |
, - * / |
日 |
是 |
1-31 |
, - * ? / L W C |
月 |
是 |
1-12 或 JAN-DEC |
, - * / |
周 |
是 |
1-7 或 SUN-SAT |
, - * ? / L C # |
年 |
否 |
1970-2099 |
, - * / |
-
通配符说明:
-
*
代表任意值,表示当前域上的任意时间段都会触发
-
?
忽略当前域,它只能用在周和日两个域。因为二者会相互影响
-
-
区间连接符,表示时间范围。例如在Minutes域使用5-20,表示从5分到20分钟每分钟触发一次
-
,
表示给当前域指定多个枚举值 (并列值)
-
/
表示起始时间开始触发,然后每隔固定时间触发一次
比如分钟上设置0/5表示,从第0分钟开始每5分钟执行一次,
-
L
即last
,表示最后的意思。表示当前域的最后一秒,最后一分钟执行,执行方式由所在域决定
-
W
表示在离当前日期最近的那个工作日触发,注意:是工作日
在日字段上置”15W”,表示离每月15号最近的那个工作日触发。
如果15号正好是周六,则找最近的周五(14号)触发,
如果15号是周日,则找最近的下周一(16号)触发
如果15号正好在工作日(周一至周五),则就在该天触发。
-
#
只能用在周这个域上面
比如5#2
表示在每月的第二个周五,如果指定的时间不存在则不会触发
-
LW
表示在本月的最后一个工作日触发
-
常见的使用示例:
每10秒执行一次:*/10 * * * * ?
每10分钟执行一次:0 */10 * * * ?
每天上午11:15触发:0 15 11 ? * * 或者 0 15 11 * * ?
在每天下午2点到下午2:59期间的每1分钟触发:0 * 14 * * ?
在每天下午2点到下午2:55期间的每5分钟触发:0 0/5 14 * * ?
在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发: 0 0/5 14,18 * * ?
每月5号8点执行一次:0 0 8 5 * ?
每月最后一天8点执行一次:0 0 8 L * ?
每月最后一周内的任意天数的1点执行一次:0 0 1 ? * L
在每小时的15分、17分、19分各执行一次:0 15,17,19 * * * ?
注:
四、原生java实现定时任务
4.1 创建定时任务类,实现TimerTask接口,重写run方法
/**
* 定时任务
*/
public class MyTimerTask extends TimerTask {
@Override
public void run() {
//定时任务执行体----里面可以编写定时任务需要执行的具体逻辑
System.out.println("定时任务执行!");
}
}
4.2 创建java定时器,并执行定时任务
public class TimerTest {
public static void main(String[] args) {
Timer timer = new Timer(); //java定时器
//调用timer的schedule方法执行定时任务
//第二个参数为Long代表第一次延迟多久执行, 为Date代表第一次执行的具体时间是什么时候
//第三个参数为延迟执行时间,也就是每隔多久执行一次定时任务中的run方法,单位为毫秒
timer.schedule(new MyTimerTask(), startDate, 24 * 60 * 60 * 1000);
}
}
4.3 Spring中使用java定时器
在Spring项目中使用java原生定时器通常会在项目启动时就开启定时任务
写法如下:
@Component
public class TimerListener implements ApplicationListener<ContextRefreshedEvent> {
private Timer timer = new Timer(); //java定时器
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
//防止spring容器 和 springmvc容器导致此方法执行两次
//root application context 没有parent,他就是最顶层.
if(contextRefreshedEvent.getApplicationContext().getParent() == null){
//需要执行的逻辑代码,当spring容器初始化完成后就会执行该方法。
System.out.println("开启定时任务!");
//调用timer的schedule方法执行定时任务
//第二个参数为Long代表第一次延迟多久执行, 为Date代表第一次执行的具体时间是什么时候
//第三个参数为延迟执行时间,也就是每隔多久执行一次定时任务中的run方法,单位为毫秒
timer.schedule(new MyTimerTask(), startDate, 24 * 60 * 60 * 1000);
}
}
}