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
英文地址,請注明出處:http://en.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;不能控制訪問頻率之…