SpringBoot:@Schedule定时任务

一,@Schedule

    SpringBoot内置了Sping Schedule定时框架,通过注解驱动方式添加所注解方法到定时任务,根据配置定时信息定时执行

二,定时任务实现

    1,开启定时任务

package com.gupao.springboot;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableAsync
// 开启定时任务
@EnableScheduling
@MapperScan(basePackages = {"com.gupao.springboot.*.mapper"})
public class GupaoSpringbootApplication {

	public static void main(String[] args) {
		SpringApplication.run(GupaoSpringbootApplication.class, args);
	}

}

    2,定时任务,方法上有注释

package com.gupao.springboot.schedules;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * 定时任务演示
 * @author pj_zhang
 * @create 2018-12-26 21:19
 **/
@Component
public class ScheduleTestTask {

    // 如果方法执行时间超过定时器时间, 方法执行完成后直接执行任务
    @Scheduled(fixedRate = 3000)
    public void test_1() {
        System.out.println("fixedRate : " + new Date());
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    // 方法执行完成后, 停留间隔时间, 再次执行该方法
    // 不因为方法执行时间长度影响定时器
    @Scheduled(fixedDelay = 3000)
    public void test_2() {
        System.out.println("fixedDelag : " + new Date());
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    // 固定间隔时间执行, 方法执行完成后, 按照间隔时间点再次执行该方法
    // 比如方法执行5s, 定时间隔为3s, 则中间有一次执行不上, 从第6s开始下一次执行
    @Scheduled(cron = "0/3 * * * * *")
    public void test_3() {
        System.out.println("corn       : " + new Date());
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

    3,测试

    * 可以看到三个线程按照线程争抢方式依次执行,与三个定时器并行不相符,原因何在?

    * 进入Spring Schedule源码org.springframework.scheduling.config.ScheduledTaskRegistrar#scheduleTasks

protected void scheduleTasks() {
        if(this.taskScheduler == null) {
            // 从这一行可以看出, 定时调度任务初始化时候初始化了一个单线程的线程池
            // 所以在定时任务调度时候, 如果定时任务过多, 就会存在线程争抢
            // 而且每一次也只会有一个定时任务运行
            this.localExecutor = Executors.newSingleThreadScheduledExecutor();
            this.taskScheduler = new ConcurrentTaskScheduler(this.localExecutor);
        }

    }

三,定时任务线程池配置

    1,可以通过配置信息更改定时调度任务线程池数量

package com.gupao.springboot.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;

import java.util.concurrent.Executors;

/**
 * 更改定时器线程池初始化数量配置信息
 * @author pj_zhang
 * @create 2018-12-26 21:27
 **/
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        // 修改初始化线程数为100
        scheduledTaskRegistrar.setScheduler(Executors.newScheduledThreadPool(100));
    }
}

    * 执行结果,根据时间点可以看到,各个定时任务并行执行,不存在线程争抢

四,corn表达式

    1,先放个大招,在线corn表达式生成器

          * http://cron.qqe2.com/

    2,表达式基本公式

          * * * * * * * 分别对应,七个*分别对应单位为:秒,分,时,日,月,星期,年

    3,字段含义

字段 取值范围 特殊字符
0~59的整数 ,- * /
0~59的整数 ,- * /
0~23的整数 ,- * /
1~31的整数 ,- * ? / L W
1~12的整数 ,- * /
星期 1~7的整数或者SUN~SAT(1=SUN) ,- * ? / L #
1970~2099 ,- * /

        * "," :表示列出枚举值,例如分钟使用5,20,则表示5和20分钟各执行一次

        * "-" :表示范围,例如分钟使用5-20,表示5-20分钟每分钟触发一次

        * "*" :表示匹配该域任意值,例如分钟使用*,表示每分钟都会执行一次

        * "/" :表示起始时间开始触发,以后每隔多长时间触发一次,例如秒使用0/3,表示从0开始触发,后每三分钟触发一次

        * "?":只能在日和星期使用,表示匹配任意值,但实际不会;因为日和星期可能会存在冲突,如果想表示每月20号0点执行,则需要写为 0 0 0 20 * ?,星期位必须写为?,虽然概念上*也表示通配

        * "L" :表示最后,只出现在日和星期;例如在星期的5L,表示最后一个星期五触发

        * "W" :表示有效工作日(周一-周五),只出现在日,如果指定的当天在某月刚好为周末,则就近取周五或周一执行

        * "LW" :连用表示每个月最后一个星期五,只在日使用

        * "#" :用于确定第几个星期的星期几,只在星期使用;例如2#3,表示在每月的第三个星期一

    4,常用表达式实例

     -- 0/3 * * * * ? :表示每三秒钟执行一次

     -- 0 0 2 1 * ? :表示每月1号凌晨两点执行任务

     -- 0 15 10 ? * MON-FRI :表示周一到周五每天早上10:15执行

     -- 0 15 10 ? * 6#3   每月的第三个星期五上午10:15触发 

猜你喜欢

转载自blog.csdn.net/u011976388/article/details/85268890