Spring Boot中Schedule你真的了解吗

前言

在实际的业务开发过程中,我们经常会需要定时任务来帮助我们完成一些工作,例如每天凌晨处理报表数据,每月的月底清除上一个月的交易记录等各种各样的需求。
如果你使用的时SpringBoot框架,那么这些功能就比较容易实现了。
SpringBoot帮我们完成了相关定时任务组件的配置,我们只需要添加相应的注解@Secheduled就可以实现任务调度

实践出真知

POM包配置

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

启动类修改,开启定时调度及异步线程

@SpringBootApplication
@EnableScheduling  //开启定时任务
@EnableAsync  //开启异步,默认线程池核心线程数:8
public class ScheduledApplication {

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

}

定时任务注解

  • fixedRate:固定速率执行,例如每5秒执行一次
  • fixedDelay:固定延迟执行,例如距离上一次调用成功后2秒执行
  • initialDelay:初始延迟任务,例如任务开启过5秒后再执行,之后以固定频率或者间隔执行
  • cron:使用 Cron 表达式执行定时任务

固定速率执行编码

通过使用fixedRate参数以固定时间间隔来执行任务

	@Scheduled(fixedRate = 5000)
    public void fixeRateTask(){
        System.out.println("Fixed Rate Task,Current Thread : " + Thread.currentThread().getName());
    }

固定延迟执行编码

通过使用fixedDelay参数来设置上一次任务调用完成与下一次任务调用开始之间的延迟时间

	@Scheduled(fixedDelay = 2000)
    public void fixedDelayTask() throws InterruptedException {
        System.out.println("Fixed Delay Task,Current Thread : " + Thread.currentThread().getName());
    }

初始延迟任务编码

通过使用initialDelay参数与fixedRate或者fixedDelay搭配使用来实现初始延迟任务调度

 	@Scheduled(initialDelay = 5000,fixedRate = 5000)
    public void initialDelayTask(){
        System.out.println("Initial Delay Task,Current Thread : " + Thread.currentThread().getName());
    }

Cron表达式编码

Spring Scheduler同样支持Cron表达式,如果以上简单参数都不能满足现有的需求,可以使用 cron 表达式来定时执行任务

 	@Scheduled(cron = "*/6 * * * * ?")
    public void cronTask(){
        System.out.println("Cron Task,Current Thread : " + Thread.currentThread().getName());
    }

关于cron大家可以关注我的另一篇文章:Cron表达式详解

升华

以上的任务调度都是串行运行的,SpringBoot默认创建一个大小为1的线程池,调度任务统一使用这个线程池执行,如果某个任务耗时过长,就会影响到其他任务的正常执行,这时候我们就会考虑为什么不让任务并行执行呢,
这里我们引入异步线程池@ Async,它会创建一个线程池核心线程数为8

@Async
    @Scheduled(fixedDelay = 2000)
    public void fixedDelayTask() throws InterruptedException {
        Thread.sleep(20000);
        System.out.println("Fixed Delay Task,Current Thread : " + Thread.currentThread().getName() + ",执行时间:" + LocalDateTime.now());
    }

修改线程配置信息

  • 自定义线程池ScheduledConfig
@Configuration
public class ScheduledConfig implements SchedulingConfigurer {

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        //线程池大小
        taskScheduler.setPoolSize(10);
        //设置线程名称前缀
        taskScheduler.setThreadNamePrefix("scheduled-thread-");
        //设置线程池关闭时等待所有线程任务完成后再销毁其它的bean
        taskScheduler.setWaitForTasksToCompleteOnShutdown(true);
        //设置线程池中任务的等待时间,如果超过这个时间还没有销毁就强制销毁,以确保应用最后能被关闭
        taskScheduler.setAwaitTerminationSeconds(60);
        /**
         * 采用CallerRunsPolicy策略,当线程池没有处理能力的时候,
         * 该策略会直接在execute方法的调用线程中运行被拒绝的任务
         * 如果执行程序已关闭,则会丢弃该任务
         */
        taskScheduler.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        taskScheduler.initialize();
        //设置默认线程池
        scheduledTaskRegistrar.setTaskScheduler(taskScheduler);

    }

}

运行程序后我们会发现只有串行的调度任务线程名称被修改了,使用的我们的自定义线程池,而使用异步@Async注解的调度任务并没有使用我们自定义的线程池,这是应为@Async会自己创建一个线程池,不会使用@Secheduled的线程池,所以我们可以再自定义一个@Async的自定义线程池

@Configuration
public class MyAsyncConfigurer implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(20);
        executor.setThreadNamePrefix("MyTask-thread-");
        executor.initialize();
        return executor;
    }
}

至此有关于Spring scheduled应用实践进行分享就完成了,不足之处希望大家积极交流。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序小达人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值