日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Quartz-任务调度概述及Quartz(2.2.X)快速入门

發(fā)布時(shí)間:2025/3/21 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Quartz-任务调度概述及Quartz(2.2.X)快速入门 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 概述
  • Quartz 概述
  • Quartz 基礎(chǔ)結(jié)構(gòu)
    • Job
    • JobDetail
    • Trigger
    • Calendar
    • Scheduler
    • ThreadPool
  • 注意
  • 快速入門 Quartz(2.2.X)
    • 增加Maven依賴(Maven工程)
    • Quartz Jar 包
    • 配置文件
    • 配置
  • 實(shí)例

概述

任務(wù)調(diào)度是多數(shù)應(yīng)用系統(tǒng)的常見需求之一,我們直接編寫基于現(xiàn)成的調(diào)度程序,不但容易出錯(cuò),而且實(shí)現(xiàn)難度很大。 Quartz是任務(wù)調(diào)度領(lǐng)域非常出色的開源框架,Spring提供了繼承Quartz的功能。


首先我們來回歸下,常見的定時(shí)任務(wù):

  • OS級別的定時(shí)任務(wù)管理器

例如linux的crontab、windows自帶的計(jì)劃任務(wù)。優(yōu)點(diǎn)是:占用系統(tǒng)資源較少,而且操作簡便,是定時(shí)任務(wù)首選的實(shí)現(xiàn)方式,缺點(diǎn):當(dāng)任務(wù)數(shù)量非常大,而且任務(wù)與任務(wù)之間有因果關(guān)系、先后順序、競爭條件的話,OS級別的定時(shí)任務(wù)管理器就很難支持了。

  • 編程語言自帶的定時(shí)任務(wù)管理器

例如Java的timer和TimeTask。但是這些API提供的接口功能簡單,往往不能滿足用戶定時(shí)任務(wù)設(shè)置需要,所以在項(xiàng)目開發(fā)過程中很少使用。

  • 第三方組件

例如Java的quartz,python的celery等。這些組件往往既可以單獨(dú)部署,也可以與當(dāng)前的項(xiàng)目集成在一起統(tǒng)一部署管理,關(guān)鍵是他們有著強(qiáng)大的功能,能夠滿足我們對定時(shí)任務(wù)管理的各種需求,所以這些第三方組件往往在項(xiàng)目中應(yīng)用廣泛。


Quartz 概述

Quartz是一個(gè)開源的作業(yè)調(diào)度框架,它完全由Java寫成,并設(shè)計(jì)用于J2SE和J2EE應(yīng)用中。它提供了巨大的靈 活性而不犧牲簡單性。你能夠用它來為執(zhí)行一個(gè)作業(yè)而創(chuàng)建簡單的或復(fù)雜的調(diào)度。它有很多特征,如:數(shù)據(jù)庫支持,集群,插件,EJB作業(yè)預(yù)構(gòu)建,JavaMail及其它,支持cron-like表達(dá)式等等。

Quartz框架是一個(gè)全功能、開源的任務(wù)調(diào)度服務(wù),可以集成幾乎任何的java應(yīng)用程序—從小的單片機(jī)系統(tǒng)到大型的電子商務(wù)系統(tǒng)。Quartz可以執(zhí)行上千上萬的任務(wù)調(diào)度。

官網(wǎng)地址:http://www.quartz-scheduler.org

Quartz提供了強(qiáng)大的任務(wù)調(diào)度機(jī)制。 Quartz允許開發(fā)人員靈活的定義觸發(fā)器的調(diào)度時(shí)間表,并可對觸發(fā)器和任務(wù)進(jìn)行關(guān)聯(lián)映射。

此外Quartz提供了調(diào)度環(huán)境運(yùn)行的持久化機(jī)制,可以保存并恢復(fù)調(diào)度現(xiàn)場,即使系統(tǒng)因故障關(guān)閉,調(diào)度任務(wù)現(xiàn)場數(shù)據(jù)也不會(huì)丟失。

Quartz還提供了組件式的偵聽器、各種插件、線程池等功能


Quartz 基礎(chǔ)結(jié)構(gòu)

Quartz對任務(wù)調(diào)度的領(lǐng)域問題進(jìn)行了高度的抽象,提出了調(diào)度器、任務(wù)和觸發(fā)器這3個(gè)核心的概念,并在org.quartz通過接口和類對重要的這些核心概念進(jìn)行描述

Job(任務(wù))、JobDetail(任務(wù)細(xì)節(jié))、Trigger(觸發(fā)器)、Scheduler(任務(wù)調(diào)度器)


Job

Job是一個(gè)接口,只有一個(gè)接口方法

void execute(JobExecutionContext context)

我們只需要實(shí)現(xiàn)該接口定義需要執(zhí)行的任務(wù),把任務(wù)放在execute中執(zhí)行即可。

JobExecutionContext類提供了調(diào)度上下文的各種信息。Job運(yùn)行時(shí)的信息保存在JobDataMap實(shí)例中。


JobDetail

Quartz執(zhí)行Job時(shí),需要新建個(gè)Job實(shí)例,但是不能直接操作Job類,所以通過JobDetail來獲取Job的名稱、描述信息。 Quartz在每次執(zhí)行Job時(shí),都重新創(chuàng)建一個(gè)Job實(shí)例,但是它不直接接受一個(gè)Job的實(shí)例,相反它接收一個(gè)Job實(shí)現(xiàn)類,以便運(yùn)行時(shí)通過newInstance()的反射機(jī)制實(shí)例化Job。

因此需要通過一個(gè)類來描述Job的實(shí)現(xiàn)類及其它相關(guān)的靜態(tài)信息,如Job名字、描述、關(guān)聯(lián)監(jiān)聽器等信息,JobDetail承擔(dān)了這一角色。

重要屬性如下:

  • name:任務(wù)的名稱。

  • group:任務(wù)所在的組(默認(rèn)值:DEFAULT)。

  • jobClass:任務(wù)的實(shí)現(xiàn)類。

  • jobDataMap:傳參的作用。


Trigger

Trigger是一個(gè)類,執(zhí)行任務(wù)的規(guī)則。這個(gè)觸發(fā)器實(shí)現(xiàn)了 Trigger 接口。描述觸發(fā)Job執(zhí)行的時(shí)間觸發(fā)規(guī)則。主要有SimpleTriggerCronTrigger這兩個(gè)子類。

  • 當(dāng)僅需觸發(fā)一次或者以固定時(shí)間間隔周期執(zhí)行,SimpleTrigger是最適合的選擇;

  • CronTrigger則可以通過Cron表達(dá)式定義出各種復(fù)雜時(shí)間規(guī)則的調(diào)度方案:如每早晨9:00執(zhí)行,周一、周三、周五下午5:00執(zhí)行等;


Calendar

org.quartz.Calendar和java.util.Calendar不同, 它是一些日歷特定時(shí)間點(diǎn)的集合(可以簡單地將org.quartz.Calendar看作java.util.Calendar的集合——java.util.Calendar代表一個(gè)日歷時(shí)間點(diǎn),無特殊說明后面的Calendar即指org.quartz.Calendar)。

一個(gè)Trigger可以和多個(gè)Calendar關(guān)聯(lián), 以便排除或包含某些時(shí)間點(diǎn)。

假設(shè),我們安排每周星期一早上10:00執(zhí)行任務(wù),但是如果碰到法定的節(jié)日,任務(wù)則不執(zhí)行,這時(shí)就需要在Trigger觸發(fā)機(jī)制的基礎(chǔ)上使用Calendar進(jìn)行定點(diǎn)排除。

針對不同時(shí)間段類型,Quartz在org.quartz.impl.calendar包下提供了若干個(gè)Calendar的實(shí)現(xiàn)類,如AnnualCalendar、MonthlyCalendar、WeeklyCalendar分別針對每年、每月和每周進(jìn)行定義


Scheduler

Scheduler是最核心的概念,需要把JobDetail和Trigger注冊到scheduler中,才可以執(zhí)行。

Scheduler代表一個(gè)Quartz的獨(dú)立運(yùn)行容器Trigger和JobDetail可以注冊到Scheduler中,兩者在Scheduler中擁有各自的組及名稱,組及名稱是Scheduler查找定位容器中某一對象的依據(jù),Trigger的組及名稱必須唯一,JobDetail的組和名稱也必須唯一(但可以和Trigger的組和名稱相同,因?yàn)樗鼈兪遣煌愋偷?#xff09;。

Scheduler定義了多個(gè)接口方法,允許外部通過組及名稱訪問和控制容器中Trigger和JobDetail。

Scheduler可以將Trigger綁定到某一JobDetail中,這樣當(dāng)Trigger觸發(fā)時(shí),對應(yīng)的Job就被執(zhí)行。

一個(gè)Job可以對應(yīng)多個(gè)Trigger,但一個(gè)Trigger只能對應(yīng)一個(gè)Job。

可以通過SchedulerFactory創(chuàng)建一個(gè)Scheduler實(shí)例。

Scheduler擁有一個(gè)SchedulerContext,它類似于ServletContext,保存著Scheduler上下文信息,Job和Trigger都可以訪問SchedulerContext內(nèi)的信息。

SchedulerContext內(nèi)部通過一個(gè)Map,以鍵值對的方式維護(hù)這些上下文數(shù)據(jù),SchedulerContext為保存和獲取數(shù)據(jù)提供了多個(gè)put()和getXxx()的方法。可以通過Scheduler# getContext()獲取對應(yīng)的SchedulerContext實(shí)例。


ThreadPool

Scheduler使用一個(gè)線程池作為任務(wù)運(yùn)行的基礎(chǔ)設(shè)施,任務(wù)通過共享線程池中的線程提高運(yùn)行效率。


Job有一個(gè)StatefulJob子接口,代表有狀態(tài)的任務(wù),該接口是一個(gè)沒有方法的標(biāo)簽接口,其目的是讓Quartz知道任務(wù)的類型,以便采用不同的執(zhí)行方案。

無狀態(tài)任務(wù)在執(zhí)行時(shí)擁有自己的JobDataMap拷貝,對JobDataMap的更改不會(huì)影響下次的執(zhí)行。

而有狀態(tài)任務(wù)共享共享同一個(gè)JobDataMap實(shí)例,每次任務(wù)執(zhí)行對JobDataMap所做的更改會(huì)保存下來,后面的執(zhí)行可以看到這個(gè)更改,也即每次執(zhí)行任務(wù)后都會(huì)對后面的執(zhí)行發(fā)生影響。

正因?yàn)檫@個(gè)原因,無狀態(tài)的Job可以并發(fā)執(zhí)行,而有狀態(tài)的StatefulJob不能并發(fā)執(zhí)行,這意味著如果前次的StatefulJob還沒有執(zhí)行完畢,下一次的任務(wù)將阻塞等待,直到前次任務(wù)執(zhí)行完畢。有狀態(tài)任務(wù)比無狀態(tài)任務(wù)需要考慮更多的因素,程序往往擁有更高的復(fù)雜度,因此除非必要,應(yīng)該盡量使用無狀態(tài)的Job。

如果Quartz使用了數(shù)據(jù)庫持久化任務(wù)調(diào)度信息,無狀態(tài)的JobDataMap僅會(huì)在Scheduler注冊任務(wù)時(shí)保持一次,而有狀態(tài)任務(wù)對應(yīng)的JobDataMap在每次執(zhí)行任務(wù)后都會(huì)進(jìn)行保存。

Trigger自身也可以擁有一個(gè)JobDataMap,其關(guān)聯(lián)的Job可以通過JobExecutionContext#getTrigger().getJobDataMap()獲取Trigger中的JobDataMap。不管是有狀態(tài)還是無狀態(tài)的任務(wù),在任務(wù)執(zhí)行期間對Trigger的JobDataMap所做的更改都不會(huì)進(jìn)行持久,也即不會(huì)對下次的執(zhí)行產(chǎn)生影響。

Quartz擁有完善的事件和監(jiān)聽體系,大部分組件都擁有事件,如任務(wù)執(zhí)行前事件、任務(wù)執(zhí)行后事件、觸發(fā)器觸發(fā)前事件、觸發(fā)后事件、調(diào)度器開始事件、關(guān)閉事件等等,可以注冊相應(yīng)的監(jiān)聽器處理感興趣的事件。


注意

不同的版本的jar包,具體的操作不太相同,但是思路是相同的;比如1.8.6jar包中,JobDetail是個(gè)類,直接通過構(gòu)造方法與Job類關(guān)聯(lián)。SimpleTrigger和CornTrigger是類;在2.0.2jar包中,JobDetail是個(gè)接口,SimpleTrigger和CornTrigger是接口


上圖描述了Scheduler的內(nèi)部組件結(jié)構(gòu),SchedulerContext提供Scheduler全局可見的上下文信息,每一個(gè)任務(wù)都對應(yīng)一個(gè)JobDataMap,虛線表達(dá)的JobDataMap表示對應(yīng)有狀態(tài)的任務(wù).


快速入門 Quartz(2.2.X)

增加Maven依賴(Maven工程)

這里我們使用2.2.3 版本,后續(xù)的案例都是基于此版本。

<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz --> <dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.2.3</version> </dependency>

Quartz Jar 包

Quartz 解壓后包含了幾個(gè) jar 文件,位于lib目錄下。Quartz 的主要包名稱為 quartz-xxx.jar(xxx 表示版本號)。

要使用 Quartz 提供的特性,這個(gè) jar 包必須添加到項(xiàng)目的 classpath 中。

Quartz 根目錄 /lib 目錄下包含了 Quartz 的一系列依賴包。如果要使用 Quartz 的完整功能,那么這些 jar 包也要添加到項(xiàng)目的 classpath 中。

如果需要?jiǎng)?chuàng)建獨(dú)立的 Quartz 應(yīng)用程序,那么建議將所有的這些包都添加到項(xiàng)目 classpath 中。

如果你是在 web 服務(wù)器中使用 Quartz,那么這些第三方包可能在你的 classpath 中已經(jīng)存在,這時(shí)你需要選擇你的項(xiàng)目具體需要哪個(gè) jar 包。


配置文件

Quartz 使用的配置文件是 quartz.properties。如果使用最基本的配置,那么這個(gè)文件不是必須的,否則,這個(gè)文件必須包含在 classpath 中。

如果你創(chuàng)建的是 web 應(yīng)用程序,那么 quartz.properties 文件需要部署到 WEB-INF/classes 中,也就是 classpath 中。


配置

Quartz 的最大優(yōu)勢就是可配置。最好的配置方式是編寫 quartz.properties 文件并放到項(xiàng)目的 classpath 中。

Quartz 發(fā)布包中包含了幾個(gè)配置文件的例子,它們放在發(fā)布包的 /examples 目錄下。建議創(chuàng)建新的 quartz.properties 文件進(jìn)行配置,而不是拷貝例子中的 quartz.properties 文件來修改。這樣做的配置文件將會(huì)更加整潔,并且你也會(huì)學(xué)習(xí)到更多 Quartz 提供的特性。

作為快速起步,我們配置一個(gè)最基本的 quartz.properties 文件:

org.quartz.scheduler.instanceName = MyScheduler org.quartz.threadPool.threadCount = 3 org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

創(chuàng)建調(diào)度器時(shí),會(huì)應(yīng)用上面的配置,配置解釋如下:

  • org.quartz.scheduler.instanceName – 創(chuàng)建的調(diào)度器命名為 MyScheduler

  • org.quartz.threadPool.threadCount – 線程池中有 3 個(gè)線程,這意味著最多只能同時(shí)運(yùn)行 3 個(gè)任務(wù)。

  • org.quartz.jobStore.class – 所有 Quartz的數(shù)據(jù),例如任務(wù)和觸發(fā)器的數(shù)據(jù)都存放到內(nèi)存中(而不是數(shù)據(jù)庫中)。即使你使用了數(shù)據(jù)庫同時(shí)也使用了 Quartz,也建議使用 RamJobStore。


實(shí)例

現(xiàn)在,我們已經(jīng)下載并安裝了 Quartz,是時(shí)候開始編寫一個(gè)樣例程序了。下面的代碼得到了一個(gè) Scheduler(調(diào)度器),并調(diào)用了調(diào)度器的開始和結(jié)束操作。

package com.xgj.quartz.quartzItself.quickDemo;import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.impl.StdSchedulerFactory;public class QuartzTest {public static void main(String[] args) {try {// Grab the Scheduler instance from the FactoryScheduler scheduler = StdSchedulerFactory.getDefaultScheduler();// startscheduler.start();// shutdownscheduler.shutdown();} catch (SchedulerException e) {e.printStackTrace();}}}

一旦使用 StdSchedulerFactory.getDefaultScheduler() 獲得了 Scheduler,那么你的程序?qū)⒉粫?huì)停止,除非我們顯式調(diào)用scheduler 的 shutdown 方法。這是因?yàn)橐恢倍加谢顒?dòng)的線程。

如果你沒有配置日志,那么所有的日志將會(huì)在控制臺打印:

INFO StdSchedulerFactory - Using default implementation for ThreadExecutor INFO SimpleThreadPool - Job execution threads will use class loader of thread: main INFO SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl INFO QuartzScheduler - Quartz Scheduler v.2.2.3 created. INFO RAMJobStore - RAMJobStore initialized. INFO QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.2.3) 'DefaultQuartzScheduler' with instanceId 'NON_CLUSTERED'Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.NOT STARTED.Currently in standby mode.Number of jobs executed: 0Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.INFO StdSchedulerFactory - Quartz scheduler 'DefaultQuartzScheduler' initialized from default resource file in Quartz package: 'quartz.properties' INFO StdSchedulerFactory - Quartz scheduler version: 2.2.3 INFO QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started. INFO QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutting down. INFO QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED paused. INFO QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutdown complete.

如果需要處理我們的任務(wù),需要在 start() 和 shutdown() 方法之間添加代碼:

package com.xgj.quartz.quartzItself.quickDemo;import static org.quartz.JobBuilder.newJob; import static org.quartz.SimpleScheduleBuilder.simpleSchedule; import static org.quartz.TriggerBuilder.newTrigger;import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.Trigger; import org.quartz.impl.StdSchedulerFactory;public class QuartzTest {public static void main(String[] args) {try {// Grab the Scheduler instance from the FactoryScheduler scheduler = StdSchedulerFactory.getDefaultScheduler();// startscheduler.start();// define the job and tie it to our SimpleJob classJobDetail job = newJob(SimpleJob.class).withIdentity("job1","group1").build();// Trigger the job to run now, and then repeat every 40 secondsTrigger trigger = newTrigger().withIdentity("trigger1", "group1").startNow().withSchedule(simpleSchedule().withIntervalInSeconds(40).repeatForever()).build();// Tell quartz to schedule the job using our triggerscheduler.scheduleJob(job, trigger);// shutdown if needed// scheduler.shutdown();} catch (SchedulerException e) {e.printStackTrace();}}}

SimpleJob.class如下 ,簡單的打印時(shí)間

package com.xgj.quartz.quartzItself.quickDemo;import java.text.SimpleDateFormat;import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException;/*** * * @ClassName: SimpleJob* * @Description: 實(shí)現(xiàn)Job接口,定義需要執(zhí)行的任務(wù)。 JobExecutionContext類提供了調(diào)度上下文的各種信息。* Job運(yùn)行時(shí)的信息保存在JobDataMap實(shí)例中。* * @author: Mr.Yang* * @date: 2017年10月6日 上午11:56:43*/public class SimpleJob implements Job {@Overridepublic void execute(JobExecutionContext context)throws JobExecutionException {SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");System.out.println(" triggered time is " + dateFormat.format(new java.util.Date()));} }

運(yùn)行日志

....... INFO QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.triggered time is 2017-10-06 11:07:02triggered time is 2017-10-06 11:07:42triggered time is 2017-10-06 11:08:22 ........ ........ ........ ........

我們沒有顯式的調(diào)用shutdown方法,所以一直運(yùn)行。

《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的Quartz-任务调度概述及Quartz(2.2.X)快速入门的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。