任務(wù)調(diào)度是指基于給定時(shí)間點(diǎn)森篷,給定時(shí)間間隔或者給定執(zhí)行次數(shù)自動(dòng)執(zhí)行任務(wù)。
Java中幾種任務(wù)調(diào)度方式
- Timer
- ScheduledExecutor
Timer
使用 Timer 實(shí)現(xiàn)任務(wù)調(diào)度的核心類是 Timer 和 TimerTask篮幢。其中 Timer 負(fù)責(zé)設(shè)定 TimerTask 的起始與間隔執(zhí)行時(shí)間。使用者只需要?jiǎng)?chuàng)建一個(gè) TimerTask 的繼承類,實(shí)現(xiàn)自己的 run 方法惠拭,然后將其丟給 Timer 去執(zhí)行即可。
Timer 的設(shè)計(jì)核心是一個(gè) TaskList 和一個(gè) TaskThread庸论。Timer 將接收到的任務(wù)丟到自己的 TaskList 中斗蒋,TaskList 按照 Task 的最初執(zhí)行時(shí)間進(jìn)行排序拆挥。TimerThread 在創(chuàng)建 Timer 時(shí)會(huì)啟動(dòng)成為一個(gè)守護(hù)線程。這個(gè)線程會(huì)輪詢所有任務(wù),找到一個(gè)最近要執(zhí)行的任務(wù)丁存,然后休眠焊傅,當(dāng)?shù)竭_(dá)最近要執(zhí)行任務(wù)的開始時(shí)間點(diǎn)虐秋,TimerThread 被喚醒并執(zhí)行該任務(wù)模她。之后 TimerThread 更新最近一個(gè)要執(zhí)行的任務(wù),繼續(xù)休眠扛禽。
Timer 是一種定時(shí)器工具锋边,用來(lái)在一個(gè)后臺(tái)線程計(jì)劃執(zhí)行指定任務(wù),而 TimerTask 一個(gè)抽象類旋圆,它的子類代表一個(gè)可以被 Timer 計(jì)劃的任務(wù)宠默。
Timer 的缺陷:
1、Timer 管理時(shí)間延遲缺陷
但由于所有任務(wù)都是由同一個(gè)線程來(lái)調(diào)度灵巧,因此所有任務(wù)都是串行執(zhí)行的搀矫,同一時(shí)間只能有一個(gè)任務(wù)在執(zhí)行,前一個(gè)任務(wù)的延遲或異常都將會(huì)影響到之后的任務(wù)刻肄。還有Timer 是基于絕對(duì)時(shí)間的瓤球,對(duì)系統(tǒng)時(shí)間比較敏感。
2敏弃、Timer 拋出異常缺陷
如果 TimerTask 拋出 RuntimeException卦羡,Timer 會(huì)終止所有任務(wù)的運(yùn)行。
ScheduledExecutorService
對(duì)于 Timer 的缺陷,我們可以考慮 ScheduledThreadPoolExecutor 來(lái)替代绿饵。Timer 是基于絕對(duì)時(shí)間的欠肾,對(duì)系統(tǒng)時(shí)間比較敏感,而 ScheduledThreadPoolExecutor 則是基于相對(duì)時(shí)間拟赊;Timer 是內(nèi)部是單一線程刺桃,而 ScheduledThreadPoolExecutor 內(nèi)部是個(gè)線程池,所以可以支持多個(gè)任務(wù)并發(fā)執(zhí)行吸祟。
其設(shè)計(jì)思想是瑟慈,每一個(gè)被調(diào)度的任務(wù)都會(huì)由線程池中一個(gè)線程去執(zhí)行,因此任務(wù)是并發(fā)執(zhí)行的屋匕,相互之間不會(huì)受到干擾葛碧。需要注意的是,只有當(dāng)任務(wù)的執(zhí)行時(shí)間到來(lái)時(shí)过吻,ScheduedExecutor 才會(huì)真正啟動(dòng)一個(gè)線程进泼,其余時(shí)間 ScheduledExecutor 都是在輪詢?nèi)蝿?wù)的狀態(tài)。
用 ScheduledExecutor 和 Calendar 實(shí)現(xiàn)復(fù)雜任務(wù)調(diào)度
Timer 和 ScheduledExecutor 都僅能提供基于開始時(shí)間與重復(fù)間隔的任務(wù)調(diào)度纤虽,不能勝任更加復(fù)雜的調(diào)度需求缘琅。比如,設(shè)置每星期二的 16:38:10 執(zhí)行任務(wù)廓推。該功能使用 Timer 和 ScheduledExecutor 都不能直接實(shí)現(xiàn),但我們可以借助 Calendar 間接實(shí)現(xiàn)該功能翩隧。
XXL-JOB
http://www.xuxueli.com/xxl-job/#/?id=%E3%80%8A%E5%88%86%E5%B8%83%E5%BC%8F%E4%BB%BB%E5%8A%A1%E8%B0%83%E5%BA%A6%E5%B9%B3%E5%8F%B0xxl-job%E3%80%8B
xxl-job由調(diào)度中心和執(zhí)行器兩部分組成樊展,調(diào)度中心負(fù)責(zé)任務(wù)的調(diào)度,執(zhí)行器負(fù)責(zé)執(zhí)行任務(wù)堆生。調(diào)度中心后臺(tái)专缠,支持配置任務(wù),控制任務(wù)淑仆,查看任務(wù)運(yùn)行日志等功能涝婉。
執(zhí)行器:任務(wù)的綁定的執(zhí)行器,任務(wù)觸發(fā)調(diào)度時(shí)將會(huì)自動(dòng)發(fā)現(xiàn)注冊(cè)成功的執(zhí)行器
描述:任務(wù)的描述信息蔗怠,便于任務(wù)管理
路由策略:當(dāng)執(zhí)行器集群部署時(shí)墩弯,提供豐富的路由策略,包括寞射,
第一個(gè):固定選擇第一個(gè)機(jī)器渔工;
最后一個(gè):固定選擇最后一個(gè)機(jī)器;
輪詢:執(zhí)行器循環(huán)執(zhí)行
隨機(jī):隨機(jī)選擇在線的機(jī)器
一致性HASH:每個(gè)任務(wù)按照Hash算法固定選擇某一臺(tái)機(jī)器桥温,且所有任務(wù)均勻散列在不同機(jī)器上
最不經(jīng)常使用:使用頻率最低的機(jī)器優(yōu)先被選舉
最近最久未使用:輪詢的倒序選用
故障轉(zhuǎn)移:按照順序依次進(jìn)行心跳檢測(cè)引矩,第一個(gè)心跳檢測(cè)成功的機(jī)器選定為目標(biāo)執(zhí)行器并發(fā)起調(diào)度
忙碌轉(zhuǎn)移:按照順序依次進(jìn)行空閑檢測(cè),第一個(gè)空閑檢測(cè)成功的機(jī)器選定為目標(biāo)執(zhí)行器并發(fā)起調(diào)度
Cron:觸發(fā)任務(wù)執(zhí)行的Cron表達(dá)式
運(yùn)行模式:任務(wù)以JobHandler方式維護(hù)在執(zhí)行器端,需要結(jié)合“JobHandler”屬性匹配執(zhí)行器中任務(wù)
JobHandler:運(yùn)行模式為“Bean”時(shí)生效旺韭,對(duì)應(yīng)執(zhí)行器中新開發(fā)的JobHandler類@JobHandler注解自定義的value值
子任務(wù)Key:每個(gè)任務(wù)都擁有一個(gè)唯一的任務(wù)Key(任務(wù)Key可以從任務(wù)列表獲确彰铡),當(dāng)本任務(wù)執(zhí)行結(jié)束并且執(zhí)行成功時(shí)区端,將會(huì)觸發(fā)子任務(wù)Key所對(duì)應(yīng)的任務(wù)的一次主動(dòng)調(diào)度值漫。
阻塞處理策略:調(diào)度過于密集執(zhí)行器來(lái)不及處理時(shí)的處理策略,
單機(jī)串行:調(diào)度請(qǐng)求進(jìn)入單機(jī)執(zhí)行器后珊燎,調(diào)度請(qǐng)求進(jìn)入FIFO隊(duì)列并以串行方式運(yùn)行惭嚣;
丟棄后續(xù)調(diào)度:調(diào)度請(qǐng)求進(jìn)入單機(jī)執(zhí)行器后,發(fā)現(xiàn)執(zhí)行器存在運(yùn)行的調(diào)度任務(wù)悔政,本次請(qǐng)求將會(huì)將丟棄并標(biāo)記為失斖硗獭;
覆蓋之前調(diào)度:調(diào)度請(qǐng)求進(jìn)入單機(jī)執(zhí)行器后谋国,發(fā)現(xiàn)執(zhí)行器存在運(yùn)行的調(diào)度任務(wù)槽地,將會(huì)終止運(yùn)行中的調(diào)度任務(wù)并清空隊(duì)列,然后運(yùn)行本地調(diào)度任務(wù)失敗處理策略:
失敗告警:調(diào)度失敗時(shí)芦瘾,將會(huì)觸發(fā)失敗報(bào)警捌蚊,如發(fā)送報(bào)警郵件;
失敗重試:調(diào)度失敗時(shí)近弟,將會(huì)主動(dòng)進(jìn)行一次失敗重試調(diào)度缅糟,重試調(diào)度后仍然失敗將會(huì)觸發(fā)失敗告警。注意當(dāng)任務(wù)以failover方式路由時(shí)祷愉,每次失敗重試將會(huì)觸發(fā)新一輪路由窗宦;
執(zhí)行參數(shù):任務(wù)執(zhí)行所需的參數(shù),多個(gè)參數(shù)時(shí)用逗號(hào)分隔二鳄,任務(wù)執(zhí)行時(shí)將會(huì)把多個(gè)參數(shù)轉(zhuǎn)換為數(shù)組傳入
報(bào)警郵件:任務(wù)調(diào)度失敗時(shí)郵件通知的郵箱地址赴涵,支持配置多郵箱地址,配置多個(gè)郵箱地址時(shí)用逗號(hào)分隔