SpringBoot下的定时任务调度@Scheduled,Java原生定时任务

SpringBoot下的定时任务调度@Scheduled,Java原生定时任务

一、概述

定时任务调度,一句话概括就是:基于给定的时间点、给定的时间间隔、自动执行的任务(方法)。

二、java生态下的定时任务实现方式

  • Spring 3.0以后自带了task 调度工具简单方便,(SpringBoot项目里的主流实现方式)
  • java自带的API java.util.Timerjava.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 "";

  1. zone:时区设置,可以设置为java.util.TimeZone中的zoneId,该字段一般留空即可

  2. fixedDelay:执行完一次以后(方法完全执行完之后)隔多长的时间再去执行

    //执行完一次以后隔10000毫秒,即10秒再去执行
    @Scheduled(fixedDelay = 10000)
    
  3. fixedDelayString:与fixedDelay不同的就是只接收字符串,并且可以支持SpringEL表达式来赋值

    //执行完一次以后隔10000毫秒,即10秒再去执行
    @Scheduled(fixedDelayString = "10000")
    
    //SpringEL的赋值方式
    @Scheduled(fixedDelayString = "${Schedul.fixedDelay}")
    

    SpringEL的赋值方式 需要在application.yml中配置

    Schedul: 
    	fixedDelay: 10000
    
  4. fixedRate: 在上一次开始执行时间点(也就是方法刚开始执行的时候)之后多长时间再执行

    //在上一次开始执行时间点(也就是方法刚开始执行的时候)的10000毫秒后,即10秒后再去执行
    @Scheduled(fixedRate = 10000)                
    
  5. fixedRateString:与fixedRate不同的就是只接收字符串,并且可以支持SpringEL表达式来赋值

    //在上一次开始执行时间点(也就是方法刚开始执行的时候)的10000毫秒后,即10秒后再去执行
    @Scheduled(fixedRate = "10000")    
    
  6. initialDelay:设置第一次执行时的等待时间,即等待多长时间,再去执行第一次

    //第一次延迟2秒后执行,之后就按只有fixedRate参数的方式每10秒执行一次 
    @Scheduled(initialDelay=2000, fixedRate=10000)   
    //第一次延迟2秒后执行,之后按只有fixedDelayStrin参数的方式每10秒执行一次
    @Scheduled(initialDelay=2000, fixedDelayString=10000)   
    

    相当于initialDelay也就只对定时任务的首次执行有效

  7. initialDelayString:与initialDelay不同的就是只接收字符串,并且可以支持SpringEL表达式来赋值

  8. cron表达式:用于设置每次执行的时间间隔

    • 语法:[秒] [分] [小时] [日] [月] [周] [年]

      其中[年]不是必须的域,通常使用的时候省略[年],前6位足以满足大部分需求,并且前6位也不能省。

    • 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分钟执行一次,

      • Llast,表示最后的意思。表示当前域的最后一秒,最后一分钟执行,执行方式由所在域决定

      • 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 * * * ?
      

注:

  • ​ 对与Cron表达式理解其含义即可

  • ​ 网上很多CRON在线生成器,在实际项目应用中可以参考使用

四、原生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);
        }
    }

}

你可能感兴趣的:(Spring,java,spring,spring,boot)