第二十二章 : Spring Boot 集成定时任务(一)

第二十二章 : Spring Boot 集成定时任务(一)

前言

本章知识点: 介绍使用Spring Boot内置的@Scheduled注解来实现定时任务-单线程和多线程;以及介绍Quartz定时任务调度框架:简单定时调度器(SimpleSchedule)和Cron表达式调度器(CronSchedule)来调度触发的定时任务。

Springboot 版本 2.3.2.RELEASE ,RabbitMQ 3.9.11,Erlang 24.2

场景

  1. 系统维护:操作系统和各种软件通常需要定期进行更新和打补丁。通过定时任务,这些更新可以在预定时间自动进行,无需人工干预。
  2. 文件同步:在多个设备或服务器之间同步文件时,可以使用定时任务来确保文件的一致性。例如,使用cron在Linux系统上定期同步文件夹。
  3. 发送通知或警报:许多系统需要定期发送通知或警报,如系统状态报告,警报阈值越过通知等。这些可以通过定时任务来实现。
  4. 数据抽取和加载:在大数据环境中,通常需要从不同的数据源抽取数据,并将其加载到数据仓库或分析系统中。定时任务可以定期执行这些操作。
  5. 测试和监控:定期进行系统或应用的健康检查,性能测试等,以便及时发现问题并进行修复。
  6. 日志清理:定期清理过期的日志文件,以防止磁盘空间被耗尽。
  7. 网关定期同步:对于需要和远程系统进行同步的网关服务,定时任务可以帮助实现数据的定期更新。
  8. 定期重新启动服务:某些服务可能需要定期重新启动以保持良好的性能。定时任务可以执行这个操作。
  9. 定期更新统计信息:在各种系统中,统计信息的及时更新对于决策制定和性能优化都非常重要。定时任务可以帮助实现这个需求。

Spring Boot定时任务的方式

Spring Boot提供了两种实现定时任务的方式:

1) 一种是Spring Boot内置的注解方式,只需在类上增加@Scheduled即可实现;

2)另一种是基于Quartz实现,Quartz是目前完善的定时任务解决方案,适合处理复杂的应用场景。

@Scheduled定时任务
参数说明
  1. value:指定计划任务的时间间隔。可以是固定时间间隔的字符串表示,例如"0 0/5 * * * ?"表示每5分钟执行一次。也可以是cron表达式,例如"0 0 12 * * ?"表示每天中午12点执行。
  2. fixedRate:固定速率,表示任务以固定的时间间隔执行。如果设置了该参数,那么方法会在每隔一定时间间隔后执行一次。与value参数类似,参数值可以是固定的时间间隔字符串或cron表达式。
  3. fixedDelay:固定延迟,表示任务在完成一次执行后,等待一定的延迟时间再执行下一次。与value参数类似,参数值可以是固定的时间间隔字符串或cron表达式。
  4. initialDelay:初始延迟,表示任务在启动后需要等待一定的延迟时间才开始执行。参数值可以是固定的时间间隔字符串或cron表达式。
  5. cron:cron表达式,用于指定任务的执行时间。可以精确到秒级别。例如,"0 0 12 * * ?"表示每天中午12点执行。
  6. timezone:时区,用于指定任务的执行时间。该参数通常与cron表达式一起使用,以确定任务在特定时区中的执行时间。
  7. threadName:线程名称,用于指定执行任务的线程名称。如果未设置该参数,则默认使用"ScheduledThreadExecutor"。
  8. inheritable:是否可继承,表示是否允许子类继承该注解的设置。默认为false。
  9. stateful:是否状态保持,表示是否在每次执行任务时都保持状态。默认为false。
  10. jobName:任务名称,用于指定计划任务的名称。如果未设置该参数,则默认使用方法名称作为任务名称。
  11. jobGroup:任务组,用于将相关的计划任务分组在一起执行。如果未设置该参数,则默认使用方法所属的类作为任务组。
代码示例

Spring Boot提供了内置的@Scheduled注解实现定时任务的功能。使用@Scheduled注解创建定时任务非常简单,只需几行代码即可完成。

注意:默认情况下,Spring Boot定时任务是单线程方式执行的。

如果同一时刻有两个定时任务需要执行,那么只能在一个定时任务完成之后再执行下一个。

如果只有一个定时任务,这样做肯定没问题;当定时任务增多时,如果一个任务被阻塞,则会导致其他任务无法正常执行。要解决这个问题,需要配置任务调度线程池。

单线程定时任务
  1. 创建定时任务类

    首先创建SchedulerTask类,然后在任务方法上添加@Scheduled注解,@EnableScheduling开启定时任务,具体的代码如下:

    import lombok.extern.slf4j.Slf4j;
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Component;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    @EnableScheduling
    @Component
    @Slf4j
    public class SchedulerTask {
    
        @Scheduled(cron="*/10 * * * * ?")
        protected void taskCron(){
            SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
            log.info("现在时间Scheduled1: {}" , dateFormat.format(new Date()));
        }
    }
    
  2. 启动项目

    创建好SchedulerTask定时任务后启动项目,查看后台任务的运行情况,如图22-1所示。

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication(scanBasePackages = "org.sea.example.day14.task")
    public class SpringbootDay14Application {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringbootDay14Application.class, args);
        }
    
    }
    

    在这里插入图片描述

    ​ 图22-1 后台定时任务执行日志

    后台日志显示,SchedulerTask任务每隔10秒输出当前时间,说明定义的任务正在后台定时执行

多线程定时任务
  1. 增加多线程配置类

    增加SchedulerConfig配置类,代码如下:

    import lombok.extern.slf4j.Slf4j;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
    
    import java.util.concurrent.Executor;
    @Configuration
    @Slf4j
    public class SchedulerConfig {
    
        @Bean
        public Executor asyncTaskScheduler() {
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(3);
            executor.setMaxPoolSize(10);
            executor.setQueueCapacity(3);
            executor.initialize();
            log.info("多线程配置类初始化");
            return executor;
        }
    }
    

    设置执行线程池为3,最大线程数为10。

  2. SchedulerTask定时任务

    在类上增加@EnableAsync注解,在方法上增加@Async注解,使得后台任务能够异步执行,代码如下:

    mport lombok.extern.slf4j.Slf4j;
    import org.springframework.scheduling.annotation.Async;
    import org.springframework.scheduling.annotation.EnableAsync;
    import org.springframework.scheduling.annotation.EnableScheduling;
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Component;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    @EnableAsync
    @EnableScheduling
    @Component
    @Slf4j
    public class SchedulerAsyncTask {
    
        @Async
        @Scheduled(cron="*/10 * * * * ?")
        protected void task1(){
            SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
            log.info("现在时间Scheduled1: {}" , dateFormat.format(new Date()));
        }
    
        @Async
        @Scheduled(cron="*/10 * * * * ?")
        protected void task2(){
            SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
            log.info("现在时间Scheduled2: {}" , dateFormat.format(new Date()));
        }
    
        @Async
        @Scheduled(cron="*/10 * * * * ?")
        protected void task3(){
            SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
            log.info("现在时间Scheduled3: {}" , dateFormat.format(new Date()));
        }
    }
    

    ​ 在上面的示例中,定时任务类SechedulerTask增加了@EnableAsync注解,开启了异步事件支持。同时,在定时方法上增加@Async注解,使任务能够异步执行,这样各个后台任务就不会阻塞。

    1. 启动项目

      创建好SchedulerTask定时任务后启动项目,查看后台任务的运行情况,如图22-2所示。

      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      
      @SpringBootApplication(scanBasePackages = "org.sea.example.day14.task2")
      public class SpringbootDay14Application {
      
          public static void main(String[] args) {
              SpringApplication.run(SpringbootDay14Application.class, args);
          }
      
      }
      
      

      在这里插入图片描述

      ​ 图22-2 后台定时任务执行日志

      通过后台日志可以看到,Spring Boot启动线程池负责调度执行后台任务,各个后台任务之间相对独立、互不影响。

Quartz

1、什么是Quartz?

Quartz是OpenSymphony开源组织在任务调度(Job Scheduling,也称为作业调度)领域下的开源项目,它是Java开发的开源任务调度管理系统,具有使用灵活、配置简单的特点,能够实现复杂应用场景下的任务调度管理。当定时任务愈加复杂时,使用Spring Boot注解@Scheduled已经不能满足业务需要。相比之下,Quartz灵活而又不失简单,能够创建简单或复杂的调度任务,其主要具有如下功能:

1)持久化:将任务和状态持久化到数据库。

2)任务管理:对调度任务进行有效的管理。

3)集群:借助关系数据库和JDBC任务存储支持集群。

2、 Quartz的基本概念

Quartz是一个由Java开发的开源框架,用于执行定时任务。以下是Quartz的一些基本概念:

  1. Job:Job是一个接口,代表一个具体的任务。任务的具体逻辑在execute方法中实现。每次执行Job时,Quartz都会重新创建一个Job实例。
  2. JobDetail:用于定义Job的实例。因为相同的任务逻辑可能会被多次执行,所以使用JobDetail来创建每个独立的Job实例,确保各个任务可以独立运行。
  3. Trigger:Trigger是一个接口,用于定义执行给定Job的时间规则。主要有SimpleTrigger和CronTrigger这两个子接口。
  4. Scheduler:Scheduler是一个接口,代表Quartz的独立运行容器,用于与调度程序交互。
  5. JobBuilder:用于定义或构建JobDetail实例,帮助创建Job的实例。
  6. TriggerBuilder:用于定义或构建Trigger实例。

Trigger和JobDetail可以注册到Scheduler中,两者在Scheduler中拥有各自的组和名称,组和名称是Scheduler查找、定位容器中某个对象的依据,Trigger的组和名称必须唯一,JobDetail的组和名称也必须唯一(但可以与Trigger的组和名称相同,因为它们是不同类型的)。Scheduler定义了多个接口方法,允许外部通过组和名称访问控制容器中的Trigger与JobDetail。

总而言之,Scheduler相当于一个容器,其中包含各种Job和Trigger,四者之间的关系如图22-3所示

在这里插入图片描述

​ 图22-3 四者之间的关系图

Quartz通过Scheduler触发Trigger规则实现任务的管理和调度。除此之外,Quartz还提供了TriggerBuilderJobBuilder类来构建Trigger实例和Job实例。

Quartz主要有简单定时调度器(SimpleSchedule)和Cron表达式调度器(CronSchedule)来调度触发的定时任务。下面通过示例演示这两种调度器的用法。

简单定时调度器(SimpleSchedule
  1. 添加Quartz依赖

    在pom.xml中配置Quartz的依赖包spring-boot-starter-quartz,具体配置如下:

    		<dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-quartz</artifactId>
            </dependency>
    
  2. 创建任务

    创建定时任务的实现类SimpleJob,并继承QuartzJobBean,示例代码如下:

    import lombok.extern.slf4j.Slf4j;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    import org.springframework.scheduling.quartz.QuartzJobBean;
    
    @Slf4j
    public class SimpleJob extends QuartzJobBean {
    
    
        private String name;
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            log.info(String.format("Hello %s!", this.name));
        }
    }
    
  3. 构建JobDetail、CronTrigger

    接下来构建JobDetail和Trigger实例。首先使用SimpleScheduleBuilder创建Scheduler实例,然后关联JobDetail和Trigger实例。示例代码如下:

    import org.quartz.*;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class SimpleScheduler {
    
        @Bean
        public JobDetail simpleJobDetail() {
            return JobBuilder.newJob(SimpleJob.class).withIdentity("simpleJobDetail")
                    .usingJobData("name", "test simpleJob")
                    .storeDurably()
                    .build();
        }
    
        @Bean
        public Trigger sampleJobTrigger() {
            SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                    .withIntervalInSeconds(10).repeatForever();
            return TriggerBuilder
                    .newTrigger()
                    .forJob(simpleJobDetail())
                    .withIdentity("sampleJobTrigger")
                    .withSchedule(scheduleBuilder).build();
        }
    }
    
  4. 运行任务

    启动项目,验证任务是否能正常运行。如图22-4所示,

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    /**修改scanBasePackages */
    @SpringBootApplication(scanBasePackages = "org.sea.example.day14.job")
    public class SpringbootDay14Application {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringbootDay14Application.class, args);
        }
    
    }
    

    在这里插入图片描述

    ​ 图22-4 简单任务运行日志

    SimpleJob后台任务成功运行,每隔10秒执行一次,这说明使用SimpleSchedule创建简单的定时任务运行成功。

Cron表达式调度器(CronSchedule
  1. 定义Job

    import lombok.extern.slf4j.Slf4j;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    import org.springframework.scheduling.quartz.QuartzJobBean;
    
    @Slf4j
    public class CronJob extends QuartzJobBean {
    
    
        private String name;
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            log.info(String.format("Hello %s!", this.name));
        }
    }
    
  2. 构建JobDetail、CronTrigger

    import org.quartz.*;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class CronScheduler {
    
        @Bean
        public JobDetail cronJobDetail() {
            return JobBuilder.newJob(CronJob.class).withIdentity("cronJobDetail")
                    .usingJobData("name", "test cronJob")
                    .storeDurably()
                    .build();
        }
    
        @Bean
        public Trigger cronJobTrigger() {
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/10 * * * * ?");
            return TriggerBuilder
                    .newTrigger()
                    .forJob(cronJobDetail())
                    .withIdentity("cronJobTrigger")
                    .withSchedule(scheduleBuilder).build();
        }
    }
    
  3. 运行任务

    启动项目,验证任务是否能正常运行。如图22-5所示,

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    /**修改scanBasePackages */
    @SpringBootApplication(scanBasePackages = "org.sea.example.day14.job2")
    public class SpringbootDay14Application {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringbootDay14Application.class, args);
        }
    
    }
    

    在这里插入图片描述

    ​ 图22-5 Cron定时任务运行日志

    CronJob后台任务成功运行,每隔10秒执行一次,这说明使用CronScheduleBuilder创建简单的定时任务运行成功。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/261988.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【EI会议征稿通知】2024年计算机与多媒体技术国际学术会议(ICCMT 2024)

2024年计算机与多媒体技术国际学术会议&#xff08;ICCMT 2024&#xff09; 2024 International Conference on Computer and Multimedia Technology (ICCMT 2024) 2024年计算机与多媒体技术国际学术会议&#xff08;ICCMT2024&#xff09;将于3月1日-3日在福建三明举办。会议…

Atium Designer 23 全新功能-丝印制备,解决DFM问题

进行PCB设计时需要养成良好的设计习惯&#xff0c;才能保证后期的生产效果。例如整板上需要保证丝印跟阻焊的间距规则避免产生丝印重叠造成的PCB制造设计&#xff08;DFM&#xff09;问题。丝印重叠阻焊的影响有如下&#xff1a; 1&#xff09;PCB板后期打样&#xff0c;一般是…

基础题总结(三)

一.0的个数 代码如下 二.序列求和

解决苹果应用商城审核拒绝的Guideline 2.5.4 - Performance - Software Requirements问题

当您的应用程序在苹果应用商城审核过程中被拒绝时&#xff0c;苹果会向您发送一封邮件&#xff0c;其中提供了关于拒绝原因的详细信息。本文将深入探讨如何正确处理Guideline 2.5.4 - Performance - Software Requirements问题&#xff0c;并提供解决方案&#xff0c;以确保您的…

gitee的学习

1.git下载 下载地址&#xff1a;https://git-scm.com/ 2.建立远程仓库 访问&#xff1a;gitee.com 在此网站上创建 3.本地操作 在本地找一个任意文件&#xff0c;克隆git 执行命令&#xff1a;git clone https://gitee.com/beijing-jiaxin-times_0/test_zsx_cang_ku.git …

tcp vegas 为什么好

我吹捧 bbr 时曾论证过它在和 buffer 拧巴的时候表现如何优秀&#xff0c;但这一次说 vegas 时&#xff0c;我说的是从拥塞控制这个问题本身看来&#xff0c;vegas 为什么好&#xff0c;并且正确。 接着昨天 tcp vegas 鉴赏 继续扯。 假设一群共享带宽的流量中有流量退出或有…

版本控制器git

1、下载 官网下载地址&#xff1a;https://git-scm.com/download 如果觉得官网下载慢的话&#xff0c;可以考虑某些应用市场&#xff0c;比如腾讯的 2、安装 安装就没什么可说的了&#xff0c;一直下一步就行了。 安装完毕后&#xff0c;回到桌面右键&#xff0c;如果出现这…

GLTF vs FBX:应该使用哪种格式?

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 概括地说&#xff0c;如果要将数据传输到 Unity 或虚幻引擎等游戏引擎…

用VS Code修改源代码的编码格式

用VS Code打开一个编码格式为GB2312的源代码文件&#xff0c;中文部分显示为乱码 这是因为VS Code默认解码格式为UTF-8 此时我们点击上面红框这个位置&#xff0c;命令面板弹出两个选项&#xff0c;选择通过编码重新打开 可以看到VS Code已经猜测出该文件就是GB 2312编码的…

DDPM推导笔记

各位佬看文章之前&#xff0c;可以先去看看这个视频&#xff0c;并给这位up主点赞投币&#xff0c;这位佬讲解的太好了&#xff1a;大白话AI 1.前置知识的学习 1.1 正态分布特性 ​ &#xff08;1&#xff09;正态分布的概率密度函数 f ( x ) 1 2 π σ e − ( x − μ ) …

机器学习 | 集成学习

团结就是力量&#xff01; Ensemble Learning 兼听则明&#xff0c;偏信则暗。 集成学习既是一种思想也是一类算法&#xff0c;它是建立在其他机器学习的算法之上&#xff0c;研究怎么让不同的算法之间进行协同。 既可以监督学习&#xff0c;也可以无监督学习。 集成学习用机器…

本地运行vue脚手架 从下载node开始到创建vue

vue2node 1.安装node vue2版本我node一般使用的是14版本左右 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/f886442c20114e62aef8113425e34ad2.pngnode官网 假如我node版本过低 你就找到控制面板 找到node卸载掉 我一般下载两个版本 安装vue cli vuecl…

element下拉框背景/选中/鼠标移入样式设置

问题在页面内写穿透无效 <style lang"scss" scoped> // 这个有效::v-deep .el-input--mini .el-input__inner {background: transparent;color: #fff;border: 1px solid #093B9E;} </style>直接在标签内写 <style> .el-select-dropdown__list {b…

【uniapp】uniapp中本地存储sqlite数据库保姆级使用教程(附完整代码和注释)

数据库请求接口封装 uniapp中提供了plus.sqlite接口&#xff0c;在这里我们对常用的数据库请求操作进行了二次封装 这里的dbName、dbPath、recordsTable 可以根据你的需求自己命名 module.exports {/** * type {String} 数据库名称*/dbName: salary,/*** 数据库地址* type {…

3842充电器电路图大全

3842充电器电路图&#xff08;一&#xff09; UC3842组成的充电器电路 图1中C1、V1&#xff5e;V4、C2组成滤波整流电路&#xff0c;变压器T为高频变压器&#xff0c;V5、R2、C11组成功率开关管V7的保护电路&#xff0c;NF为供给IC电源的绕组。单端输出IC为UC3842&#xff0c;…

在Linux安装的Docker中开启IPv6

先在Linux中安装docker&#xff0c;然后在docker中开启IPv6。 安装docker 第一步&#xff0c;卸载旧版本docker。 若系统中已安装旧版本docker&#xff0c;则需要卸载旧版本docker以及与旧版本docker相关的依赖项。 命令&#xff1a;yum -y remove docker docker-client do…

Sirius:一款功能强大的通用漏洞扫描工具

关于Sirius Sirius是一款功能强大的通用漏洞扫描工具&#xff0c;该工具可以帮助广大研究人员在大多数场景下识别和验证应用程序中存在的安全漏洞。 现如今&#xff0c;信息安全社区仍然是收集网络安全情报数据最佳且最有利的来源&#xff0c;而且社区本身的表现经常会优于商…

SparkSQL的编程模型(DataFrame和DataSet)

1.2 SparkSQL的编程模型(DataFrame和DataSet) 1.2.1 编程模型简介 主要通过两种方式操作SparkSQL&#xff0c;一种就是SQL&#xff0c;另一种为DataFrame和Dataset。 SQL SQL不用多说&#xff0c;就和Hive操作一样&#xff0c;但是需要清楚一点的时候&#xff0c;SQL操作的是…

C#联合halcon开发,连接相机颜色不对,无法连接相机

相机可以在海康软件MVS中打开&#xff08;颜色正常&#xff09;&#xff0c;但是在C#开发的程式中无法打开&#xff08;彩色相机颜色显示异常&#xff09;。 1.异常处理 1.查看相机和MVS软件是否连接成功&#xff1b; 2.如果成功&#xff0c;连接C#程序&#xff1b; 3.程序连接…

usb端口管理软件有哪些(usb端口管理软件)

USB端口管理软件在当今的计算机使用中扮演着越来越重要的角色。随着USB设备的普及&#xff0c;如U盘、移动硬盘、数码相机等&#xff0c;相应的管理软件也变得越来越受欢迎。 1、USB端口管理软件可以帮助用户更好地管理和控制U盘的使用。 在插入U盘时&#xff0c;软件可以自动…