第二十二章 : 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 {@Beanpublic 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;}@Overrideprotected 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 {@Beanpublic JobDetail simpleJobDetail() {return JobBuilder.newJob(SimpleJob.class).withIdentity("simpleJobDetail").usingJobData("name", "test simpleJob").storeDurably().build();}@Beanpublic 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;}@Overrideprotected 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 {@Beanpublic JobDetail cronJobDetail() {return JobBuilder.newJob(CronJob.class).withIdentity("cronJobDetail").usingJobData("name", "test cronJob").storeDurably().build();}@Beanpublic 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创建简单的定时任务运行成功。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu 18.04 共享屏幕

用于windows远程ubuntu 1. sudo apt install xrdp 2. 配置 sudo vim /etc/xrdp/startwm.sh 把最下面的test和exec两行注释掉&#xff0c;添加一行 gnome-session 3.安装dconf-editor : sudo apt-get install dconf-editor 关闭require encrytion org->gnome->desktop…

TransXNet实战:使用TransXNet实现图像分类任务(一)

文章目录 摘要安装包安装timm 数据增强Cutout和MixupEMA项目结构计算mean和std生成数据集 摘要 论文提出了一种名为D-Mixer的轻量级双动态TokenMixer&#xff0c;旨在解决传统卷积的静态性质导致的表示差异和特征融合问题。D-Mixer通过应用高效的全局注意力和输入依赖的深度卷…

Py之tensorflow-addons:tensorflow-addons的简介、安装、使用方法之详细攻略

Py之tensorflow-addons&#xff1a;tensorflow-addons的简介、安装、使用方法之详细攻略 目录 tensorflow-addons的简介 tensorflow-addons的安装 tensorflow-addons的使用方法 1、使用 TensorFlow Addons 中的功能&#xff1a; tensorflow-addons的简介 TensorFlow Addon…

【SpringBoot快速入门】(4)SpringBoot项目案例代码示例

目录 1 创建工程3 配置文件4 静态资源 之前我们已经学习的Spring、SpringMVC、Mabatis、Maven&#xff0c;详细讲解了Spring、SpringMVC、Mabatis整合SSM的方案和案例&#xff0c;上一节我们学习了SpringBoot的开发步骤、工程构建方法以及工程的快速启动&#xff0c;从这一节开…

Python---TCP 客户端程序开发

1. 开发 TCP 客户端程序开发步骤回顾 创建客户端套接字对象和服务端套接字建立连接发送数据接收数据关闭客户端套接字 2. socket 类的介绍 导入 socket 模块 import socket 创建客户端 socket 对象 socket.socket(AddressFamily, Type) 参数说明: AddressFamily 表示IP地…

JavaScript:函数

JavaScript&#xff1a;函数 函数的作用函数的声明和调用函数声明函数调用函数重复声明 函数传参传参语法参数默认值与参数数量问题传参数量过多传参数量太少参数默认值 函数的返回值函数表达式匿名函数立即执行函数 函数的作用 在我们编程过程中&#xff0c;会出现一种情况&a…

[软件] Image2LCD v4.0

介绍 通过打开图片, 可以提取图片的像素特征, 生成.c文件, 或者二进制文件等, 提供人们根据需要选择. 16位真彩色 每一个像素点需要用16位来表示, 分别是RGB, R: 5位 G: 6位, B: 5位, 共两个字节. 配置 tftLCD180显示屏, 官方给的参考代码, 需要如下所示设置.

【Spring Security】认证密码加密Token令牌CSRF的使用详解

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《Spring Security》。&#x1f3af;&#x1f3af; …

频谱论文:RadioUNet:使用卷积神经网络的快速无线电地图估计

#频谱# R. Levie, . Yapar, G. Kutyniok and G. Caire, "RadioUNet: Fast Radio Map Estimation With Convolutional Neural Networks," in IEEE Transactions on Wireless Communications, vol. 20, no. 6, pp. 4001-4015, June 2021, doi: 10.1109/TWC.2021.305497…

【hadoop】解决浏览器不能访问Hadoop的50070、8088等端口?!

【hadoop】解决浏览器不能访问Hadoop的50070、8088等端口&#xff1f;&#xff01;&#x1f60e; 前言&#x1f64c;【hadoop】解决浏览器不能访问Hadoop的50070、8088等端口&#xff1f;&#xff01;查看自己的配置文件&#xff1a;最终成功访问如图所示&#xff1a; 总结撒花…

10 个顶级免费 Android 数据恢复软件可帮助恢复已删除的文件

不小心删除了手机上的一些重要数据或文件&#xff1f;这很不幸&#xff0c;但不要悲伤或放弃希望&#xff0c;因为仍有机会恢复它们。 10 个顶级免费 Android 数据恢复软件 虽然 Android 手机没有像 Windows 那样的回收站可以自动存储您删除的数据&#xff0c;但是有很多功能强…

【Java中的负数取绝对值结果为什么不一定是正数?】

Java中的负数取绝对值结果为什么不一定是正数&#xff1f; ✅典型解析✅扩展知识仓✅整型的取值范围✅超出范围怎么办 ✅典型解析 假如&#xff0c;我们要用Math.abs对一个nteger取绝对值的时候&#xff0c;如果用如下方式: Math .abs(orderId.hashCode());得到的结果可能是个负…

在Java Web开发中,Servlet功能与jsp功能可以相互转换吗

在Java Web开发中&#xff0c;Servlet和JSP是两种常用的Web组件&#xff0c;它们可以相互协作&#xff0c;也可以相互转换。 具体来说&#xff0c;Servlet可以实现所有JSP的功能&#xff0c;而JSP也可以调用Servlet中的方法。Servlet可以通过Java代码生成HTML页面&#xff0c;而…

一键转换,将HTML智能转换为PDF,轻松解决文档转换需求

在数字时代&#xff0c;HTML网页是我们获取信息的主要来源之一。然而&#xff0c;有时候我们可能需要将网页内容以PDF格式保存&#xff0c;以便于离线阅读、打印或分享。这时&#xff0c;将HTML转换为PDF就变得尤为重要。 首先&#xff0c;我们要进入首助编辑高手主页面&#x…

[CVPR-23] Instant Volumetric Head Avatars

[paper | code | proj] 本文提出INSTA。INSTA是一种backward mapping方法。该方法基于NeRF建立标准空间&#xff0c;形变空间&#xff08;任意表情&#xff09;通过映射回标准空间&#xff0c;实现渲染。为实现形变空间中任意点向标准空间的映射&#xff0c;对形变空间中的任意…

C++ Qt开发:TabWidget实现多窗体功能

Qt 是一个跨平台C图形界面开发库&#xff0c;利用Qt可以快速开发跨平台窗体应用程序&#xff0c;在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置&#xff0c;实现图形化开发极大的方便了开发效率&#xff0c;本章将重点介绍TabWidget标签组件的常用方法及灵活运用。 Q…

MVVM响应式

聚沙成塔每天进步一点点 本文内容 ⭐ 专栏简介MVVM响应式1. 什么是MVVM模式?2. Vue中的响应式数据3. 数据绑定与视图更新⭐ 写在最后⭐ 专栏简介 Vue学习之旅的奇妙世界 欢迎大家来到 Vue 技能树参考资料专栏!创建这个专栏的初衷是为了帮助大家更好地应对 Vue.js 技能树的学习…

IspSrver-DNS

2023年全国网络系统管理赛项真题 模块B-Windows解析 题目 安装DNS服务器,根据题目创建必要正向区域和反向区域的DNS解析。把当前机器作为互联网根域服务器,创建test1.com~test100.com,并在所有正向区域中创建一条A记录,解析到本机地址。配置步骤 安装DNS服务器,根据题目创…

3842充电器电路图大全

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

Nacos-服务发现与配置管理v1.0

Nacos - 服务发现和配置管理 教学目标 1&#xff09;能够理解微服务架构的特点 2&#xff09;能够理解服务发现的流程 3&#xff09;能够说出Nacos的功能 4&#xff09;掌握Nacos的安装方法 5&#xff09;掌握RESTful服务发现开发方法 6&#xff09;掌握Dubbo服务发现开…