SpringBoot扩展——定时任务!

定时任务

项目开发中会涉及很多需要定时执行的代码,如每日凌晨对前一日的数据进行汇总,或者系统缓存的清理、对每日的数据进行分析和总结等需求,这些都是定时任务。单体系统和分布式系统的分布式任务有很大的区别,单体系统就一个任务执行类,非常简单,分布式系统则要保证定时任务执行的唯一性,不能让一个定时任务被执行多次。

实现定时任务的5种方式

Java定时任务目前主要有以下5种实现方式。

JDK自带的实现方式,如JDK自带的Timer和JDK 1.5+新增的ScheduledExecutor- Service;

elastic-job:功能完备的分布式定时任务框架;

Spring 3.0以后自带的task:可以将它看成一个轻量级的任务调度;

使用Quartz实现定时任务;

分布式任务调度:可以使用国产组件XXL-Job实现。

下面分别讲解不同的定时任务的实现。

实战:基于JDK方式实现简单定时

使用JDK方式实现定时任务有两种方法:

(1)第一种是使用Timer类进行实现,Timer是JDK自带的定时任务执行类,任何项目都可以直接使用Timer来实现定时任务,因此Timer的优点就是使用方便。但是Timer的缺点也很明显,这是个单线程的实现,如果任务执行时间太长或者发生异常,则会影响其他任务执行。在开发和测试环境中可以用Timer类进行测试,强烈建议在生产环境中谨慎使用,使用Timer实现的定时任务代码如下:

package com.example.springextenddemo.dingshi;

import java.time.LocalDateTime;

import java.time.format.DateTimeFormatter;

import java.util.Timer;

import java.util.TimerTask;

public class TimerDemo {

//定义时间格式

private static DateTimeFormatter pattern =

DateTimeFormatter.ofPattern

("yyyy-MM-dd HH:MM:ss");

public static void main(String[] args) {

Timer timer = new Timer();

/**

* 从当前时刻开始,每1s执行一次,方法的入参单位为毫秒(ms,1000毫秒即

1s)

*/

timer.schedule(new MyTask(),0,1000);

}

/**

* 自定义任务实现

*/

private static class MyTask extends TimerTask {

@Override

public void run() {

LocalDateTime now = LocalDateTime.now();

System.out.println("这是定时任务,时间

是:"+pattern.format(now));

}

}

}

执行当前的main()方法,可以看到控制台打印的定时任务日志如图6.10所示。

图6.10 Timer定时任务

Timer类设定定时任务有以下3种重载方法:

schedule(TimerTask task, long delay):延迟delay毫秒再执行任务;

schedule(TimerTask task, Date time):在特定的时间执行任务;

schedule(TimerTask task, long delay, long period):延迟delay毫秒执行并每隔period毫秒执行一次。

(2)使用JDK实现定时任务的第二种方式就是使用ScheduledExecutorService类。该类是Java 1.5后新增的定时任务接口,主要有以下几种方法:

public interface ScheduledExecutorService extends ExecutorService {

public ScheduledFuture<?> schedule(Runnable command,

long delay, TimeUnit unit); public <V> ScheduledFuture<V> schedule(Callable<V> callable,

long delay, TimeUnit unit);

public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,

long initialDelay,

long period,

TimeUnit unit);

public ScheduledFuture<?> scheduleWithFixedDelay(Runnable

command,

long initialDelay,

long delay,

TimeUnit unit);

}

ScheduledExecutorService类的基本原理和Timer相似,下面使用ScheduledExecutor- Service实现和Timer一样的定时任务功能:

package com.example.springextenddemo.dingshi;

import java.time.LocalDateTime;

import java.time.format.DateTimeFormatter;

import java.util.concurrent.Executors;

import java.util.concurrent.ScheduledExecutorService;

import java.util.concurrent.TimeUnit;

public class ScheduledExecutorServiceDemo {

//时间格式

private static DateTimeFormatter pattern =

DateTimeFormatter.ofPattern

("yyyy-MM-dd HH:MM:ss");

public static void main(String[] args) {

ScheduledExecutorService service =

Executors.newScheduledThreadPool(1);

service.scheduleAtFixedRate(() -> { LocalDateTime now = LocalDateTime.now();

System.out.println("schedule 这是定时任务,时间是:" +

pattern.format(now));

}, 0, 1000, TimeUnit.MILLISECONDS);

}

}

执行main()方法,控制台打印的日志如图6.11所示,与上面的Timer实现了相同的效果。在开发过程中,如果只是简单的定时任务,建议直接采用ScheduleExecutorsService类来处理,这是线程池技术,能够实现线程的复用。

实战:基于Spring Task实现定时任务

Spring Task的核心实现类位于spring-context包中,在Spring项目中可以直接使用该定时任务类。下面演示Spring Task定时任务的实现过程。添加一个新的类SpringTaskDemo,代码如下:

package com.example.springextenddemo.dingshi;

import org.springframework.scheduling.annotation.EnableScheduling;

import org.springframework.scheduling.annotation.Scheduled;

import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

import java.time.format.DateTimeFormatter;

@EnableScheduling //开启定时任务

@Component

public class SpringTaskDemo {

private static DateTimeFormatter pattern =

DateTimeFormatter.ofPattern

("yyyy-MM-dd HH:MM:ss");

/**

* 每秒钟执行一次

*/

@Scheduled(cron = "0/1 * * * * ?")

public void cron() {

LocalDateTime now = LocalDateTime.now();

System.out.println("spring task 这是定时任务,时间是:" +

pattern.format(now));

}

}

再次启动SpringBoot项目,然后就可以自动启动Spring Task了,定时任务执行结果如图6.12所示。@EnableScheduling注解表示开启SpringTask任务,如果不开启,就没有办法执行定时任务。@Scheduled(cron = "0/1 * ** * ?")注解表示每分钟执行一次,注解中的“0/1 * * * * ?”是cron表达式,cron表达式包括Seconds、Minutes、Hours、Day-of-Month、Month、Day-of-Week和Year(可选字段),它们之间以空隔分隔。读者可根据要实现的业务完成cron表达式的拼接。cron中一些特殊字符的含义如表6.3所示。

@Scheduled注解支持非常多的参数,以帮助开发者快速完成定时任务的开发,这些参数如下:

cron:cron表达式,指定任务在特定的时间执行;

fixedDelay:上一次任务执行完成后隔多长时间再次执行,参数类型为long,单位为ms;

fixedDelayString:与fixedDelay的含义一样,只是参数类型变为String;

fixedRate:按一定的频率执行任务,参数类型为long,单位为ms;fixedRateString:与fixedRate的含义一样,只是参数类型变为String;

initialDelay:第一次任务延迟多久再执行,参数类型为long,单位为ms;

initialDelayString:与initialDelay的含义一样,只是参数类型变为String;

zone:时区,默认为当前时区,一般不用。

基于Spring Task强大的功能和便捷性,在开发Spring项目时,笔者推荐

使用Spring Task完成定时任务的需求。

实战:基于Quartz实现定时调度

Quartz是一个由Java编写的开源任务调度框架,其通过触发器设置作业定时运行规则,控制作业的运行时间。Quartz还可以搭建成集群服务,其中,Quartz集群通过故障切换和负载平衡的功能,能给调度器带来高可用性和伸缩性。我们一般用Quartz来执行定时任务,如定时发送信息、定时生成报表等。在分布式系统中,也可以使用Quartz完成任务调度的需求。

Quartz框架的核心组件包括调度器、触发器和作业。调度器是作业的总指挥,触发器是作业的操作者,作业为应用的功能模块。

Quartz框架中的Job为任务接口,该接口只有一个方法voidexecute(JobExecution- Context context),自定义定时任务的类需要实现Job接口并重写execute()方法,在该方法中完成定时业务逻辑。

JobExecutionContext类提供了调度上下文的各种信息。每次执行Job时均需要重新创建一个Job实例。

下面再介绍几个Quartz常用的几个类:JobDetail类用来描述Job的实现类及其他相关的静态信息;Trigger类是定时任务的定时管理工具,一个Trigger只能对应一个定时任务,而一个定时任务却可对应多个触发器;

Scheduler类是定时任务的管理容器,是Quartz最上层的接口,它管理所有触发器和定时任务,使它们协调工作,每个Scheduler都保存有JobDetail和Trigger的注册信息,一个Scheduler类中可以注册多个JobDetail和多个Trigger。

基于以上介绍,使用Quartz重新实现6.2.2小节的定时任务。

(1)在pom.xml中添加Quartz的依赖,其坐标如下:

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-quartz</artifactId>

</dependency>

(2)修改log4j2.xml的日志记录器,添加Quartz包的日志级别为INFO,不要打印DEBUG级别的日志。

<loggers>

<!--Spring和MyBatis的日志级别为INFO-->

<logger name="org.springframework" level="INFO"></logger>

<logger name="org.mybatis" level="INFO"></logger>

<logger name="org.quartz" level="INFO"></logger>

<!-- 自定义包设置为INFO,则可以看见输出的日志不包含DEBUG输出了 -->

<logger name="com.example.springextenddemo" level="INFO"/>

<root level="all">

<appender-ref ref="myAppender"/>

</root>

</loggers>

(3)自定义任务执行类,添加Quartz的任务类:

package com.example.springextenddemo.dingshi;import org.quartz.JobExecutionContext;

import org.quartz.JobExecutionException;

import org.springframework.scheduling.quartz.QuartzJobBean;

import java.time.LocalDateTime;

import java.time.format.DateTimeFormatter;

public class MyQuartzTask extends QuartzJobBean{

private static DateTimeFormatter pattern =

DateTimeFormatter.ofPattern

("yyyy-MM-dd HH:MM:ss");

@Override

public void executeInternal(JobExecutionContext context) throws

JobExecutionException {

LocalDateTime now = LocalDateTime.now();

System.out.println("quartz 这是定时任务,时间是:" +

pattern.format(now));

}

}

(4)添加Quzrtz的配置类,配置定时任务的执行时间和频率。

package com.example.springextenddemo.dingshi;

import org.quartz.*;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

@Configuration

public class QuartzConfig {

@Bean

public JobDetail testQuartz1() {

return JobBuilder.newJob(MyQuartzTask.class).withIdentity

("myQuartzTask") .storeDurably().build();

}

@Bean

public Trigger testQuartzTrigger1() {

//1s执行一次

SimpleScheduleBuilder scheduleBuilder =

SimpleScheduleBuilder.simpleSchedule()

.withIntervalInSeconds(1)

.repeatForever();

return TriggerBuilder.newTrigger().forJob(testQuartz1())

.withIdentity("myQuartzTask")

.withSchedule(scheduleBuilder)

.build();

}

}

(5)启动当前项目会自动加载定时任务,通过控制台就能看到Quartz定时任务的执行情况,控制台打印的日志如图6.13所示。

至此,在项目中使用定时任务的例子便介绍完了,在开发中可以直接使用Timer或者ScheduledExecutorService进行定时任务的测试,在实际的生产环境中,应根据项目情况选择使用Spring Task或者Quartz来实现需求。

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

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

相关文章

RTDETRv2 pytorch 官方版自己数据集训练遇到的问题解决

rtdetrv2 训练问题遇到的问题。 pip install torch2.0.1 torchvision0.15.2 torchaudio2.0.2 --index-url https://download.pytorch.org/whl/cu117 1 Please make sure torchvision version > 0.15.2 发现自己实际装的是 torchvison0.15.2cu117 修改_misc.py中修改为…

Linux系统移植⑤:uboot启动流程详解-board_init_f执行过程

Linux系统移植⑤&#xff1a;uboot启动流程详解-board_init_f执行过程 _main 中会调用 board_init_f 函数。 board_init_f 函数主要有两个工作&#xff1a; ①初始化一系列外设&#xff0c;比如串口、定时器&#xff0c;或者打印一些消息等。 ②初始化 gd 的各个成员变量&am…

Git命令与代码仓库管理

步骤一、完成Gitee码云上账号注册并新建代码仓库。 1.1 新建代码仓库 1.2 填写信息并创建 1.3 获取仓库地址 https://gitee.com/dog-kidney/2022082206.git 步骤二、建立本地代码仓库&#xff0c;并连接到远程代码仓库。 2.1初始化 git init 2.2添加仓库 git remote add o…

资源占用多,Linux 系统中如何降低 CPU 资源消耗并提升利用率?

在 Linux 系统中降低 CPU 资源消耗并提升利用率,需从系统服务优化、进程管理、资源调度及内核参数调整等多维度入手。以下是适用于各类 Linux 发行版的通用优化方案,涵盖基础操作与进阶策略: 一、服务与进程优化:减少无效资源占用 1. 关闭冗余系统服务 查看运行中的服务 …

技术与情感交织的一生 (八)

目录 融合 东西厂公 接风宴 头痛 “巴巴罗萨” 突击 推进 助攻 96小时 寒冬 食堂 反攻 消耗 Delphi 西厂 内困 外患 “敦刻尔克” 多线作战 大撤退 资源 融合 东西厂公 初次来到纸箱厂&#xff0c;是主厂区&#xff0c;感觉很大&#xff0c;相对西面正在…

webuploader分片上传示例,服务端上传文件到腾讯云CDN Teo 应用示例

本文环境&#xff1a;php7.3.4 CI3.0框架 一、大概步骤&#xff1a; &#xff08;1&#xff09;利用百度的webuploader插件&#xff0c;将大文件分片上传的自己的服务器 &#xff08;2&#xff09;利用腾讯云接口从本服务器上传到腾讯云 二、详细代码&#xff1a; 1、进入…

LeetCode 632.最小区间

你有 k 个 非递减排列 的整数列表。找到一个 最小 区间&#xff0c;使得 k 个列表中的每个列表至少有一个数包含在其中。 我们定义如果 b-a < d-c 或者在 b-a d-c 时 a < c&#xff0c;则区间 [a,b] 比 [c,d] 小。 示例 1&#xff1a; 输入&#xff1a;nums [[4,10,…

篇章五 系统性能优化——资源优化——CPU优化(2)

目录 1.高级并发模式 1.1 工作窃取&#xff08;Work Stealing&#xff09; 1.工作窃取模式 2.ForkJoinPool实现 3.具体例子 1.2 结构化并发&#xff08;Structured Concurrency&#xff09; 1.结构化并发模式 2.Java 19 的 StructuredTaskScope 3.具体例子 1.3 对比与…

《中国电信运营商骨干网:历史、现状与未来演进》系列 第四篇:后发先至——中国移动CMNET的快速扩张与IP专网布局

摘要&#xff1a; 本文深入探讨中国移动骨干网CMNET (AS9808) 的发展历程、网络架构及其与中国电信扁平化策略的差异。同时&#xff0c;解析其为承载高价值业务而构建的IP专用承载网的定位、结构与技术特点。最后&#xff0c;展望中国移动在5G、云计算和算力网络时代&#xff0…

R情感分析:解码文本中的情感

基于之前关于文本聚类和文本模型的博客&#xff0c;我们现在可以深入探讨一个经典主题 - 情感分析。情感分析通过计算方式识别和分类文本中的情感&#xff0c;帮助理解公众意见或消费者反馈。 什么是情感分析&#xff1f; 情感分析确定文本背后的情感基调&#xff0c;将其分类…

云徙渠道订货系统:赋能企业渠道管理的数字化引擎

在当今商业竞争日益激烈的环境下&#xff0c;企业如何高效管理和优化渠道成为关键问题。云徙渠道订货系统凭借其强大的数字化能力&#xff0c;为企业提供了全新的渠道管理解决方案&#xff0c;助力企业在复杂多变的市场环境中保持竞争力。 从渠道管理的痛点出发 传统渠道管理方…

Nacos基础使用(二):nacos作为配置中心

一、Nacos 配置中心核心属性 在学习nacos 作为配置中心的使用之前&#xff0c;先看下Nacos 作为配置中心时的三个属性&#xff0c;即&#xff1a; 命名空间、配置分组、配置集ID&#xff08;习惯称为配置文件ID&#xff09;&#xff1b;在使用Nacos 作为配置中心 的过程中可以通…

SpringBoot 插件化架构的4种实现方案

在复杂业务场景下&#xff0c;传统的单体应用架构往往面临着功能扩展困难、代码耦合严重、迭代效率低下等问题。 插件化架构作为一种模块化设计思想的延伸&#xff0c;能够使系统具备更好的扩展性和灵活性&#xff0c;实现"热插拔"式的功能扩展。 本文将介绍Spring…

VGG-19(Visual Geometry Group)模型

VGG-19 是由牛津大学视觉几何组和 Google DeepMind 的研究人员在 2014 年提出的一个非常经典的深度卷积神经网络模型。 一 核心结构 &#xff08;1&#xff09;深度&#xff1a; 模型名称中的 "19" 指的是模型拥有 19 层带有权重的层&#xff08;通常指&#xff1a;…

Windows11 鼠标卡死任务栏卡死 假死解决方法

最近很多朋友都有一个问题&#xff0c;就是Windows11电脑 在编辑文档或者是切换窗口的时候出现任务栏假死&#xff0c;鼠标左右键失灵等现象&#xff0c;想了几天解决方案今天吧最直接的方法教给大家 首发玖毅论坛 玖毅论坛https://www.webbbs.cn/ 第一步&#xff1a; 第一种…

BeikeShop - 一个开源、用户友好的跨境电子商务平台

BeikeShop - 一个开源、用户友好的跨境电子商务平台 BeikeShop 是全球领先的基于 Laravel 框架的开源电子商务平台&#xff0c;专为国际贸易和跨境电子商务行业设计。 该系统是 100% 开源的&#xff01;它支持多语言、多币种、支付、物流、会员管理等广泛的实用功能&#xff0…

基于大模型的胆囊结石全周期诊疗方案研究报告

目录 一、引言 1.1 研究背景与意义 1.2 研究目的与目标 1.3 研究方法与创新点 二、大模型预测胆囊结石的原理与技术基础 2.1 大模型概述 2.2 用于胆囊结石预测的数据来源 2.3 模型构建与训练 2.4 模型评估指标 三、术前风险预测与手术方案制定 3.1 术前评估指标与数…

[论文阅读] 人工智能 | Gen-n-Val:利用代理技术革新计算机视觉数据生成

Gen-n-Val&#xff1a;利用代理技术革新计算机视觉数据生成 论文信息 article{huang2025gennval,title{Gen-n-Val: Agentic Image Data Generation and Validation},author{Huang, Jing-En and Fang, I-Sheng and Huang, Tzuhsuan and Wang, Chih-Yu and Chen, Jun-Cheng},jo…

【AI论文】ReasonMed:一个370K的多智能体生成数据集,用于推进医疗推理

摘要&#xff1a;尽管基于推理的大型语言模型&#xff08;LLM&#xff09;在数学和编程方面表现出色&#xff0c;但它们在知识密集型医疗问题回答方面的能力仍未得到充分探索。为解决这一问题&#xff0c;我们推出了ReasonMed&#xff0c;这是最大的医疗推理数据集&#xff0c;…

singlefligt使用方法和源码解读

singlefligt使用方法和源码解读 介绍 sync.once保证其整个生命周期内只调用一次&#xff1b;而singleflight则可以保证在一定范围内其只调用一次。 背景|使用场景 应对缓存击穿&#xff1a;加锁可以解决这个问题&#xff0c;但是加锁不太灵活&#xff08;不能控制访问频率之…