Quartz 的启动流程分析
一、簡(jiǎn)要
1.1、quartz 的核心元素
Scheduler為調(diào)度器負(fù)責(zé)整個(gè)定時(shí)系統(tǒng)的調(diào)度,內(nèi)部通過線程池進(jìn)行調(diào)度,下文闡述。
Trigger為觸發(fā)器記錄著調(diào)度任務(wù)的時(shí)間規(guī)則,主要有四種類型:SimpleTrigger、CronTrigger、DataIntervalTrigger、NthIncludedTrigger,在項(xiàng)目中常用的為:SimpleTrigger和CronTrigger。
JobDetail為定時(shí)任務(wù)的信息載體,可以記錄Job的名字、組及任務(wù)執(zhí)行的具體類和任務(wù)執(zhí)行所需要的參數(shù)
Job為任務(wù)的真正執(zhí)行體,承載著具體的業(yè)務(wù)邏輯。
(像我們昨天的小案例中,簡(jiǎn)單定時(shí)任務(wù)就是實(shí)現(xiàn)了 job 接口)
大致流程就是:
- 先由?SchedulerFactory?創(chuàng)建?Scheduler?調(diào)度器
- 再由?Scheduler?調(diào)度器去調(diào)取即將執(zhí)行的?Trigger?,
- 執(zhí)行時(shí)獲取到對(duì)于的?JobDetail?信息,
- 最后找到對(duì)應(yīng)的?Job?類執(zhí)行業(yè)務(wù)邏輯。
1.2、quartz中的線程
-
執(zhí)行線程主要由一個(gè)線程池維護(hù),在需要執(zhí)行定時(shí)的時(shí)候使用,
-
這里使用的線程池是?org.quartz.simpl.SimpleThreadPool?,默認(rèn)線程數(shù)為 10
(這些在程序啟動(dòng)過程中的打印信息處就能看到)
- 調(diào)度線程主要分為?Regular Scheduler Thread?和?Misfire Scheduler Thread?;
- 其中?Regular Thread 輪詢Trigger?,如果有將要觸發(fā)的Trigger,則從任務(wù)線程池中獲取一個(gè)空閑線程,然后執(zhí)行與改Trigger關(guān)聯(lián)的job;
- Misfire Thraed?則是掃描所有的trigger,查看是否有錯(cuò)失的,如果有的話,根據(jù)一定的策略進(jìn)行處理。
二、quartz 啟動(dòng)流程
通常是使用?StdSchedulerFactory?創(chuàng)建?Scheduler?調(diào)度器。
在?SchedulerFactoryBean?配置類中配了相關(guān)的配置及配置文件參數(shù),所以會(huì)讀取配置文件參數(shù),初始化各個(gè)組件。
啟動(dòng)流程的大致步驟如下:
2.1、讀取配置文件
這里的讀取,沒有去debug,配置文件的位置是在
org.quartz?的包下,文件名為?quartz.properties
其內(nèi)容為:
2.2、初始化SchedulerFactoryBean
當(dāng)服務(wù)器啟動(dòng)時(shí),Spring就加載相關(guān)的bean。
SchedulerFactoryBean實(shí)現(xiàn)了InitializingBean接口,因此在初始化bean的時(shí)候,會(huì)執(zhí)行afterPropertiesSet方法,
該方法將會(huì)調(diào)用SchedulerFactory,通常是調(diào)用StdSchedulerFactory 來創(chuàng)建Scheduler調(diào)度器
2.3、初始化SchedulerFactory
這一步是在?SchedulerFactoryBean?的?prepareSchedulerFactory?方法中進(jìn)行初始化,在上一步也已經(jīng)看到~
我們接著往下Debug
這一大段都是在獲取配置文件信息,我們直接將斷點(diǎn)放到方法的末尾,看一下里面的值,和接下來要debug的方法
到這之后,我們會(huì)回到
this.scheduler = prepareScheduler(prepareSchedulerFactory());?這一步,拿到
prepareSchedulerFactory()?返回的,接著往下走。
上面的if就不看了,直接看create方法做了什么
這里的?this.schedulerName?是?quartzScheduler
這里的?schedulerFactory.getScheduler()?是值得我們注意的,點(diǎn)進(jìn)去看,我們看看?StdSchedulerFactory?的?getScheduler()?方法做了什么呢?
引來襲來的就是quartz中的重要組件,而且都是null,這說明我們要到下一步啦
2.4、實(shí)例化執(zhí)行線程池(TheadPool)
2.5、實(shí)例化數(shù)據(jù)存儲(chǔ)
2.6、初始化QuartzScheduler
QuartzScheduler?為Scheduler的簡(jiǎn)單實(shí)現(xiàn),包括調(diào)度作業(yè)、注冊(cè)JobListener實(shí)例等方法。
2.7、new一個(gè)?QuartzSchedulerThread?調(diào)度線程
QuartzSchedulerThread?負(fù)責(zé)執(zhí)行在QuartzScheduler中注冊(cè)的觸發(fā)觸發(fā)器的線程,并開始運(yùn)行
走到就不在繼續(xù)逗留了,我們直接回到方法調(diào)用處去。
2.8、注冊(cè)監(jiān)聽器,注冊(cè)Job和Trigger
里面不再點(diǎn)進(jìn)去看如何注冊(cè)啦,想看的xdm,繼續(xù)去Debug就可以了~
到這里?SchedulerFactoryBean?初始化就算是完成了。接下來就是執(zhí)行 start()方法
2.9、?SchedulerFactoryBean?執(zhí)行start()方法
這里的start方法是bean的生命周期中的,我們關(guān)注的不是這里,
而是方法內(nèi)部的?startScheduler(this.scheduler,this.startupDelay)?方法
這兩個(gè)不接著往下看啦~,疲啦 ...
添上紅字的這兩個(gè)就不繼續(xù)看,我們關(guān)注一下?this.resources.getJobStore().schedulerStarted();?,這也是下一步驟的開始~
2.10、創(chuàng)建Cluszaizaianager線程、創(chuàng)建MisfireHandler線程
我原本想關(guān)注一下?void recoverJobs()?方法
原本我是還想點(diǎn)進(jìn)?executeInNonManagedTXLock()?方法繼續(xù)看一眼,直接看麻了,知道這里是恢復(fù)任務(wù)就行了,看起來很難受,里面更加龐大啦,主要是沒有思緒~
2.11、QuartzSchedulerThread開始執(zhí)行run方法
置?QuartzSchedulerThread?的paused=false,調(diào)度線程真正開始調(diào)度,開始執(zhí)行run方法
這才是調(diào)度的真正開始,前面都只能算是準(zhǔn)備工作吧。
什么時(shí)候觸發(fā),獲取線程執(zhí)行任務(wù),怎么查詢數(shù)據(jù)庫等等,可以說是從這里開始的。不過,咱們今天跑路了,明天或下次再來~
總結(jié)
以上是生活随笔為你收集整理的Quartz 的启动流程分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hot_s 三子一线棋
- 下一篇: 我的iPhone奇遇记