SpringBoot 使用Schedule定时框架

一、引言

         在开发过程中,我们往往需要实现一些定时功能比如执行定时任务、定时发送统计数据等,现在虽然有java有很多类似Saturn(唯品会自主研发的分布式的定时任务的调度平台),但是在一些比较小的项目而又没有搭建好的分布式定时任务中台时,可以使用Schedule定时任务框架,使用起来简单而且就算分布式项目也可以通过使用分布式锁将Schedule实现分布式定时任务功能。

二、Schedule定时框架的使用

1、添加依赖

        使用IDEA的Spring Initiallzr创建的SpringBoot 的最基本的依赖就包含了Schedule的依赖,无需引入其它依赖了。

2、在Springboot启动类上添加@EnableScheduling注解

package com.example.schedule;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@EnableScheduling
@SpringBootApplication
public class ScheduleApplication {

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

}

3、根据需要选择Schedule (fixedRate、fixedDelay、cron表达式)三种任务调度器对应的具体调度器

        3.1 fixedRate调度器(固定频率任务)

           @Scheduled(fixedRate = 3000)是上次任务开始的时候计时3秒后再次执行任务(这3秒包含了任务执行所需时间,即不用等待上一次调用完成,如果上次任务执行超过3秒就可能会存在任务重复执行的问题) ,但是这里要注意的是Schecule默认是单线程执行的,如果没设置Schecule并发执行任务的话,使用fixedRate依旧串行执行的,不会催在重复执行情况。

package com.example.schedule.schedule;

import cn.hutool.core.date.DateUtil;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScheduledTask {

    @Scheduled(fixedRate = 3000)
    public void fixedRateTest1() {
        System.out.println("fixedRate : " + DateUtil.now());
    }
}

 未设置并发fixedRate执行情况(这时候虽然设置是3秒间隔执行任务而实际间隔都是5秒):

package com.example.schedule.schedule;

import cn.hutool.core.date.DateUtil;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScheduledTask {

    @Scheduled(fixedRate = 3000)
    public void fixedRateTest1() {
        System.out.println("fixedRateTest1 : " + DateUtil.now());
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 设置并发后fixedRate执行情况(执行间隔都是3秒):

import cn.hutool.core.date.DateUtil;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScheduledTask {

    @Scheduled(fixedRate = 3000)
    @Async
    public void fixedRateTest1() {
        System.out.println(Thread.currentThread().getName()+"<>fixedRateTest1 : " + DateUtil.now());
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

    3.2 fixedDelay调度器(固定间隔任务)

           @Scheduled(fixedDelay= 3000)是指上次任务结束后再计时3秒后再次开启新的一次调用。

package com.example.schedule.schedule;

import cn.hutool.core.date.DateUtil;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScheduledTask {

    @Scheduled(fixedDelay = 3000)
    public void fixedRateTest1() {
        System.out.println(Thread.currentThread().getName()+"<>fixedRateTest1 : " + DateUtil.now());
    }
}

  3.3 cron表达式

           @Scheduled(cron = "0/3 * * * * *")是根据cron表达式执行定时任务的。

package com.example.schedule.schedule;

import cn.hutool.core.date.DateUtil;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScheduledTask {

    @Scheduled(cron = "0/3 * * * * *")
    public void cronTest1() {
        System.out.println(Thread.currentThread().getName()+"<>cronTest1 : " + DateUtil.now());
    }
}

三、Schedule其它

1、在线corn表达式生成器,可以图形化生成corn表达式:https://cron.qqe2.com/

2、 Schecule默认是单线程执行的,可以在Spring Schedule源码的org.springframework.scheduling.config.ScheduledTaskRegistrar里的scheduleTasks看到定时调度任务初始化时候初始化了一个单线程的线程池,所以在定时任务调度时候, 如果定时任务过多, 就会存在线程争抢,所以如果不设置成并发的时候当在同一时间多个任务并发执行时,任务调度器就会出现时间偏移,任务执行时间将不再和设置执行的一样。

猜你喜欢

转载自blog.csdn.net/GyaoG/article/details/124638044