前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >3分钟带你掌握Spring Boot中的定时调度服务

3分钟带你掌握Spring Boot中的定时调度服务

原创
作者头像
潘志的技术笔记
修改于 2024-07-19 09:40:29
修改于 2024-07-19 09:40:29
3140
举报
文章被收录于专栏:springbootspringboot

一、背景介绍

在实际的业务开发过程中,我们经常会需要定时任务来帮助我们完成一些工作,例如每天早上 6 点生成销售报表、每晚 23 点清理脏数据等等。

如果你当前使用的是 SpringBoot 来开发项目,那么完成这些任务会非常容易!

SpringBoot 默认已经帮我们完成了相关定时任务组件的配置,我们只需要添加相应的注解@Scheduled就可以实现任务调度!

二、方案实践

2.1、pom 包配置

pom包里面只需要引入Spring Boot Starter包即可!

代码语言:xml
AI代码解释
复制
<dependencies>
    <!--spring boot核心-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <!--spring boot 测试-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
2.2、启动类启用定时调度

在启动类上面加上@EnableScheduling即可开启定时

代码语言:java
AI代码解释
复制
@SpringBootApplication
@EnableScheduling
public class ScheduleApplication {

    public static void main(String[] args) {
        SpringApplication.run(ScheduleApplication.class, args);
    }
}
2.3、创建定时任务

Spring Scheduler支持四种形式的任务调度!

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

你可以通过使用fixedRate参数以固定时间间隔来执行任务,示例如下:

代码语言:java
AI代码解释
复制
@Component
public class SchedulerTask {

    private static final Logger log = LoggerFactory.getLogger(SchedulerTask.class);
    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * fixedRate:固定速率执行。每5秒执行一次。
     */
    @Scheduled(fixedRate = 5000)
    public void runWithFixedRate() {
        log.info("Fixed Rate Task,Current Thread : {},The time is now : {}", Thread.currentThread().getName(), dateFormat.format(new Date()));
    }
}

运行ScheduleApplication主程序,即可看到控制台输出效果:

代码语言:java
AI代码解释
复制
Fixed Rate TaskCurrent Thread : scheduled-thread-1The time is now : 2020-12-15 11:46:00
Fixed Rate TaskCurrent Thread : scheduled-thread-1The time is now : 2020-12-15 11:46:10
...
2.3.2、固定延迟执行

你可以通过使用fixedDelay参数来设置上一次任务调用完成与下一次任务调用开始之间的延迟时间,示例如下:

代码语言:java
AI代码解释
复制
@Component
public class SchedulerTask {

    private static final Logger log = LoggerFactory.getLogger(SchedulerTask.class);
    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * fixedDelay:固定延迟执行。距离上一次调用成功后2秒后再执行。
     */
    @Scheduled(fixedDelay = 2000)
    public void runWithFixedDelay() {
        log.info("Fixed Delay Task,Current Thread : {},The time is now : {}", Thread.currentThread().getName(), dateFormat.format(new Date()));
    }
}

控制台输出效果:

代码语言:java
AI代码解释
复制
Fixed Delay TaskCurrent Thread : scheduled-thread-1The time is now : 2020-12-15 11:46:00
Fixed Delay TaskCurrent Thread : scheduled-thread-1The time is now : 2020-12-15 11:46:02
...
2.3.3、初始延迟任务

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

代码语言:java
AI代码解释
复制
@Component
public class SchedulerTask {

    private static final Logger log = LoggerFactory.getLogger(SchedulerTask.class);
    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * initialDelay:初始延迟。任务的第一次执行将延迟5秒,然后将以5秒的固定间隔执行。
     */
    @Scheduled(initialDelay = 5000, fixedRate = 5000)
    public void reportCurrentTimeWithInitialDelay() {
        log.info("Fixed Rate Task with Initial Delay,Current Thread : {},The time is now : {}", Thread.currentThread().getName(), dateFormat.format(new Date()));
    }
}

控制台输出效果:

代码语言:java
AI代码解释
复制
Fixed Rate Task with Initial DelayCurrent Thread : scheduled-thread-1The time is now : 2020-12-15 11:46:05
Fixed Rate Task with Initial DelayCurrent Thread : scheduled-thread-1The time is now : 2020-12-15 11:46:10
...
2.3.4、使用 Cron 表达式

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

关于cron表达式的具体用法,可以点击参考这里: https://cron.qqe2.com/

代码语言:java
AI代码解释
复制
@Component
public class SchedulerTask {

    private static final Logger log = LoggerFactory.getLogger(SchedulerTask.class);
    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * cron:使用Cron表达式。每6秒中执行一次
     */
    @Scheduled(cron = "*/6 * * * * ?")
    public void reportCurrentTimeWithCronExpression() {
        log.info("Cron Expression,Current Thread : {},The time is now : {}", Thread.currentThread().getName(), dateFormat.format(new Date()));
    }
}

控制台输出效果:

代码语言:java
AI代码解释
复制
Cron ExpressionCurrent Thread : scheduled-thread-1The time is now : 2020-12-15 11:46:06
Cron ExpressionCurrent Thread : scheduled-thread-1The time is now : 2020-12-15 11:46:12
...
2.4、异步执行定时任务

在介绍异步执行定时任务之前,我们先看一个例子!

在下面的示例中,我们创建了一个每隔2秒执行一次的定时任务,在任务里面大概需要花费 3 秒钟,猜猜执行结果如何?

代码语言:java
AI代码解释
复制
@Component
public class AsyncScheduledTask {

    private static final Logger log = LoggerFactory.getLogger(AsyncScheduledTask.class);
    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Scheduled(fixedRate = 2000)
    public void runWithFixedDelay() {
        try {
            TimeUnit.SECONDS.sleep(3);
            log.info("Fixed Delay Task, Current Thread : {} : The time is now {}", Thread.currentThread().getName(), dateFormat.format(new Date()));
        } catch (InterruptedException e) {
            log.error("错误信息",e);
        }
    }
}

控制台输入结果:

代码语言:java
AI代码解释
复制
Fixed Delay Task, Current Thread : scheduling-1 : The time is now 2020-12-15 17:55:26
Fixed Delay Task, Current Thread : scheduling-1 : The time is now 2020-12-15 17:55:31
Fixed Delay Task, Current Thread : scheduling-1 : The time is now 2020-12-15 17:55:36
Fixed Delay Task, Current Thread : scheduling-1 : The time is now 2020-12-15 17:55:41
...

很清晰的看到,任务调度频率变成了每隔5秒调度一次!

这是为啥呢?

Current Thread : scheduling-1输出结果可以很看到,任务执行都是同一个线程!默认的情况下,@Scheduled任务都在 Spring 创建的大小为 1 的默认线程池中执行!

更直观的结果是,任务都是串行执行!

下面,我们将其改成异步线程来执行,看看效果如何?

代码语言:java
AI代码解释
复制
@Component
@EnableAsync
public class AsyncScheduledTask {

    private static final Logger log = LoggerFactory.getLogger(AsyncScheduledTask.class);
    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");


    @Async
    @Scheduled(fixedDelay = 2000)
    public void runWithFixedDelay() {
        try {
            TimeUnit.SECONDS.sleep(3);
            log.info("Fixed Delay Task, Current Thread : {} : The time is now {}", Thread.currentThread().getName(), dateFormat.format(new Date()));
        } catch (InterruptedException e) {
            log.error("错误信息",e);
        }
    }
}

控制台输出结果:

代码语言:java
AI代码解释
复制
Fixed Delay Task, Current Thread : SimpleAsyncTaskExecutor-1 : The time is now 2020-12-15 18:55:26
Fixed Delay Task, Current Thread : SimpleAsyncTaskExecutor-2 : The time is now 2020-12-15 18:55:28
Fixed Delay Task, Current Thread : SimpleAsyncTaskExecutor-3 : The time is now 2020-12-15 18:55:30
...

任务的执行频率不受方法内的时间影响,以并行方式执行!

2.5、自定义任务线程池

虽然默认的情况下,@Scheduled任务都在 Spring 创建的大小为 1 的默认线程池中执行,但是我们也可以自定义线程池,只需要实现SchedulingConfigurer类即可!

自定义线程池示例如下:

代码语言:java
AI代码解释
复制
@Configuration
public class SchedulerConfig implements SchedulingConfigurer {

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

        scheduledTaskRegistrar.setTaskScheduler(threadPoolTaskScheduler);
    }
}

我们启动服务,看看cron任务示例调度效果:

代码语言:java
AI代码解释
复制
Cron ExpressionCurrent Thread : scheduled-thread-1The time is now : 2020-12-15 20:46:00
Cron ExpressionCurrent Thread : scheduled-thread-2The time is now : 2020-12-15 20:46:06
Cron ExpressionCurrent Thread : scheduled-thread-3The time is now : 2020-12-15 20:46:12
Cron ExpressionCurrent Thread : scheduled-thread-4The time is now : 2020-12-15 20:46:18
....

当前线程名称已经被改成自定义scheduled-thread的前缀!

三、小结

本文主要围绕Spring scheduled应用实践进行分享,如果是单体应用,使用SpringBoot内置的@scheduled注解可以解决大部分业务需求,上手非常容易!

项目源代码地址:spring-boot-example-scheduled

四、参考

1、https://springboot.io/t/topic/2758

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
超详细的CentOS7.4下载与图文安装
链接:https://pan.baidu.com/s/1cRgNfZ5REf4LQMIyl5K3hQ 提取码:lp6q
全栈程序员站长
2022/08/10
6K0
超详细的CentOS7.4下载与图文安装
CentOS7 网络配置超详细ip、网关设置
点击NAT设置,点击查看DHCP设置只修改蓝色圈内,和并记住ip、子网掩码、起始IP地址、结束IP地址(后面设置ip会用到)
全栈程序员站长
2022/07/01
25.8K0
CentOS7 网络配置超详细ip、网关设置
CentOS7安装详解
本文基于vmware workstations进行CentOS7安装过程展示,关于vmware workstations安装配置本人这里不再介绍,基本过程相当于windows下安装个软件而已。
hailang2zh
2019/08/29
1.4K0
CentOS7安装详解
配置centos7 IP以及网络问题的排查
在虚拟机中NAT模式下可以直接使用 dhclient 自动获取IP地址。 ip add 可以直接查看自己的网卡信息(红色框里就是网卡的一些信息) 工作中以后一般使用的是静态IP所以我们需要把动态修改成
叶瑾
2018/06/14
2.7K0
VMware Fusion安装CentOS7并配置网络
最近在积累DevOps方面的知识,k8s就是重中之重,环境搭建就是第一步,今天就让我手把手,一步步教你在VMware Fusion安装CentOS7,并配置网络。
星星在线
2020/08/04
2K0
VMware Fusion安装CentOS7并配置网络
CentOS7安装VMware Tools
在虚拟机中,以 root 身份登录客户机操作系统,打开终端窗口并运行ls /dev命令查看是否含有cdrom目录
全栈程序员站长
2022/09/01
3.1K0
CentOS7安装VMware Tools
CentOS7中配置网络连接[通俗易懂]
刚在VMware安装好的CentOS7,默认安装是没有开启配置网卡信息的,所以连不上网。尝试用两种配置来让CentOS7开启联网功能,一种是直接打开网络功能自动获取ip,会在设定的网段下面随机分配一个ip,另一种是设置固定ip,出于某些特殊的需求,例如要在局域网内做端口映射,需要将虚拟机设置成使用固定的局域网IP,即使虚拟机重启了,其局域网ip仍然不变。
全栈程序员站长
2022/09/01
11.8K0
Centos7.4系统的虚拟机网络配置教程
前几天小编给大家分享了如何给Centos6.7版本的虚拟机配置网络,感兴趣的小伙伴可以点击进去看看。小编按照Centos6.7版本的虚拟机网络配置教程来配置Centos7.4的虚拟机网络,发现行不通啊,在踩坑之后,再勇敢的爬出来,整理了这一篇Centos7.4的虚拟机网络配置教程,希望小伙伴们在利用Centos7版本的路上少踩一些坑。话不多说,直接上教程。
Python进阶者
2018/08/03
7960
Centos7.4系统的虚拟机网络配置教程
VMware14安装CentOS7的详细教程
本篇文章主要介绍了VMware安装Centos7超详细过程(图文),具有一定的参考价值,感兴趣的小伙伴们可以参考一下
Lansonli
2021/10/09
5340
手把手教你安装Linux必备的VMware及CentOS7(保姆级教程)
        1.去VMware官网下载,链接VMware桌面虚拟机 官方中文版 软件下载 (bangtengxinxi.com),双击打开,点击下一步。
天寒雨落
2022/11/20
1.2K0
手把手教你安装Linux必备的VMware及CentOS7(保姆级教程)
使用VMware安装centos7并配置网络
2.Centos7安装包(https://www.centos.org/download/)
全栈程序员站长
2022/09/06
1.3K0
使用VMware安装centos7并配置网络
VMware下载安装教程(虚拟机详细安装教程)
前面给大家讲过了虚拟机VBox的安装,个人觉得还是没有VMware好用,因为VMware有快照功能,而VBox没有; 所以今天就给大家说下VMware的安装,有很多细节方面需要注意,不然很可能安装失败,这里就说下15.5.2的安装。建议不要安装最新版,因为我安装最新版的时候出现了一个情况,就是启动的时候要管理员身份才能打开,而且一直会停留在黑界面,进入不了设置界面,经过多个版本的尝试后,发现还是15.5.2版本的没有出现上述情况。
全栈程序员站长
2022/07/31
3.8K0
VMware下载安装教程(虚拟机详细安装教程)
VM虚拟机安装Centos7.6_64位系统_游戏服务器必备
大部分联网的游戏搭建需要centos7.6环境, 但是我们又没钱买服务器, 于是我们可以用虚拟机模拟centos7.6环境,跟服务器一模一样。
老罗说源码
2024/05/20
8770
Centos7安装并配置多网口
文章链接:https://www.mobaijun.com/posts/1316700149.html
框架师
2021/08/05
2.2K0
基础教程:2、Linux服务器安装图解
Linux是一类开放源代码和自由的类似Unix的操作系统,有众多发行版本。在服务器市场,Linux操作系统占有绝对的优势。Linux操作系统大致可以分为Redhat系列和Debian系列。
程裕强
2019/05/27
3.6K0
CentOS7环境搭建使用PhpStorm上传代码
虚拟机(Virtual Machine)指通过软件模拟的具有完整硬件系统功能的、运行在一个完全隔离环境中的完整计算机系统。
Lansonli
2021/10/09
4240
VMware虚拟机下的CentOS7网络配置
VMware界面最上面,选择虚拟机->设置:将网络连接改为桥接模式,如下图所示:
全栈程序员站长
2022/08/27
2.1K0
VMware虚拟机下的CentOS7网络配置
CentOS7 配置自己的网卡信息
在上一篇文章介绍了 新安装 Ubuntu后如何配置网卡信息【 https://www.misiyu.cn/article/125.html 】,这次又来记录下如何配置CentOS的网卡。
无道
2019/11/13
3.4K0
VMware 安装CentOS7(桥接)的安装笔记
桥接模式就是将主机网卡与虚拟机虚拟的网卡利用虚拟网桥进行通信。在桥接的作用下,类似于把物理主机虚拟为一个交换机,所有桥接设置的虚拟机连接到这个交换机的一个接口上,物理主机也同样插在这个交换机当中,所以所有桥接下的网卡与网卡都是交换模式的,相互可以访问而不干扰。在桥接模式下,虚拟机ip地址需要与主机在同一个网段,如果需要联网,则网关与DNS需要与主机网卡一致。
逆回十六夜
2019/07/19
1.6K0
xshell7怎么连接虚拟机_centos ssh
在虚拟机中操作系统比较麻烦,比如虚拟机中不能复制粘贴等,使用xshell比较简单,界面也比较人性化
全栈程序员站长
2022/09/30
8490
xshell7怎么连接虚拟机_centos ssh
推荐阅读
相关推荐
超详细的CentOS7.4下载与图文安装
更多 >
LV.1
这个人很懒,什么都没有留下~
目录
  • 一、背景介绍
  • 二、方案实践
    • 2.1、pom 包配置
    • 2.2、启动类启用定时调度
    • 2.3、创建定时任务
      • 2.3.1、固定速率执行
      • 2.3.2、固定延迟执行
      • 2.3.3、初始延迟任务
      • 2.3.4、使用 Cron 表达式
    • 2.4、异步执行定时任务
    • 2.5、自定义任务线程池
  • 三、小结
  • 四、参考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档