Java框架Quartz中的Trigger簡析
Trigger的公共屬性
所有類型的trigger都有TriggerKey這個屬性,表示trigger的身份;除此之外,trigger還有很多其它的公共屬性。這些屬性,在構建trigger的時候可以通過TriggerBuilder設置。
trigger的公共屬性有:
- jobKey屬性:當trigger觸發(fā)時被執(zhí)行的job的身份;
- startTime屬性:
- 設置trigger第一次觸發(fā)的時間;
- 該屬性的值是java.util.Date類型,表示某個指定的時間點;
- 有些類型的trigger,會在設置的startTime時立即觸發(fā),
- 有些類型的trigger,表示其觸發(fā)是在startTime之后開始生效。比如,現(xiàn)在是1月份,你設置了一個trigger–“在每個月的第5天執(zhí)行”,然后你將startTime屬性設置為4月1號,則該trigger第一次觸發(fā)會是在幾個月以后了(即4月5號)。
- endTime屬性:表示trigger失效的時間點。比如,”每月第5天執(zhí)行”的trigger,如果其endTime是7月1號,則其最后一次執(zhí)行時間是6月5號。
其它的屬性,會在下文中解釋。
優(yōu)先級(priority)
如果你的trigger很多(或者Quartz線程池的工作線程太少),Quartz可能沒有足夠的資源同時觸發(fā)所有的trigger;這種情況下,你可能希望控制哪些trigger優(yōu)先使用Quartz的工作線程,要達到該目的,可以在trigger上設置priority屬性。比如,你有N個trigger需要同時觸發(fā),但只有Z個工作線程,優(yōu)先級最高的Z個trigger會被首先觸發(fā)。如果沒有為trigger設置優(yōu)先級,trigger使用默認優(yōu)先級,值為5;priority屬性的值可以是任意整數(shù),正數(shù)、負數(shù)都可以。
注意:只有同時觸發(fā)的trigger之間才會比較優(yōu)先級。10:59觸發(fā)的trigger總是在11:00觸發(fā)的trigger之前執(zhí)行。
注意:如果trigger是可恢復的,在恢復后再調度時,優(yōu)先級與原trigger是一樣的。
錯過觸發(fā)(misfire Instructions)
trigger還有一個重要的屬性misfire;如果scheduler關閉了,或者Quartz線程池中沒有可用的線程來執(zhí)行job,此時持久性的trigger就會錯過(miss)其觸發(fā)時間,即錯過觸發(fā)(misfire)。
不同類型的trigger,有不同的misfire機制。
它們默認都使用“智能機制(smart policy)”,即根據(jù)trigger的類型和配置動態(tài)調整行為。
當scheduler啟動的時候,查詢所有錯過觸發(fā)(misfire)的持久性trigger。
然后根據(jù)它們各自的misfire機制更新trigger的信息。
當你在項目中使用Quartz時,你應該對各種類型的trigger的misfire機制都比較熟悉,這些misfire機制在JavaDoc中有說明。
關于misfire機制的細節(jié),會在講到具體的trigger時作介紹。
Simple Trigger
SimpleTrigger可以滿足的調度需求是:在具體的時間點執(zhí)行一次,或者在具體的時間點執(zhí)行,并且以指定的間隔重復執(zhí)行若干次。比如,你有一個trigger,你可以設置它在2015年1月13日的上午11:23:54準時觸發(fā),或者在這個時間點觸發(fā),并且每隔2秒觸發(fā)一次,一共重復5次。
根據(jù)描述,你可能已經發(fā)現(xiàn)了,SimpleTrigger的屬性包括:開始時間、結束時間、重復次數(shù)以及重復的間隔。這些屬性的含義與你所期望的是一致的,只是關于結束時間有一些地方需要注意。
重復次數(shù),可以是0、正整數(shù),以及常量SimpleTrigger.REPEAT_INDEFINITELY。重復的間隔,必須是0,或者long型的正數(shù),表示毫秒。注意,如果重復間隔為0,trigger將會以重復次數(shù)并發(fā)執(zhí)行(或者以scheduler可以處理的近似并發(fā)數(shù))。
如果你還不熟悉DateBuilder,了解后你會發(fā)現(xiàn)使用它可以非常方便地構造基于開始時間(或終止時間)的調度策略。
endTime屬性的值會覆蓋設置重復次數(shù)的屬性值;比如,你可以創(chuàng)建一個trigger,在終止時間之前每隔10秒執(zhí)行一次,你不需要去計算在開始時間和終止時間之間的重復次數(shù),只需要設置終止時間并將重復次數(shù)設置為REPEAT_INDEFINITELY(當然,你也可以將重復次數(shù)設置為一個很大的值,并保證該值比trigger在終止時間之前實際觸發(fā)的次數(shù)要大即可)。
指定時間開始觸發(fā),不重復:
SimpleTrigger trigger = (SimpleTrigger) newTrigger()
.withIdentity("trigger1", "group1")
.startAt(myStartTime) // some Date
.forJob("job1", "group1") // identify job with name, group strings
.build();
指定時間觸發(fā),每隔10秒執(zhí)行一次,重復10次:
trigger = newTrigger()
.withIdentity("trigger3", "group1")
.startAt(myTimeToStartFiring) // if a start time is not given (if this line were omitted), "now" is implied
.withSchedule(simpleSchedule()
.withIntervalInSeconds(10)
.withRepeatCount(10)) // note that 10 repeats will give a total of 11 firings
.forJob(myJob) // identify job with handle to its JobDetail itself
.build();
5分鐘以后開始觸發(fā),僅執(zhí)行一次:
trigger = (SimpleTrigger) newTrigger()
.withIdentity("trigger5", "group1")
.startAt(futureDate(5, IntervalUnit.MINUTE)) // use DateBuilder to create a date in the future
.forJob(myJobKey) // identify job with its JobKey
.build();
立即觸發(fā),每個5分鐘執(zhí)行一次,直到22:00:
trigger = newTrigger()
.withIdentity("trigger7", "group1")
.withSchedule(simpleSchedule()
.withIntervalInMinutes(5)
.repeatForever())
.endAt(dateOf(22, 0, 0))
.build();
建立一個觸發(fā)器,將在下一個小時的整點觸發(fā),然后每2小時重復一次:
trigger = newTrigger()
.withIdentity("trigger8") // because group is not specified, "trigger8" will be in the default group
.startAt(evenHourDate(null)) // get the next even-hour (minutes and seconds zero ("00:00"))
.withSchedule(simpleSchedule()
.withIntervalInHours(2)
.repeatForever())
// note that in this example, 'forJob(..)' is not called which is valid
// if the trigger is passed to the scheduler along with the job
.build();
scheduler.scheduleJob(trigger, job);
TriggerBuilder(以及Quartz的其它builder)會為那些沒有被顯式設置的屬性選擇合理的默認值。比如:如果你沒有調用withIdentity(…)方法,TriggerBuilder會為trigger生成一個隨機的名稱;如果沒有調用startAt(…)方法,則默認使用當前時間,即trigger立即生效。
SimpleTrigger Misfire策略
SimpleTrigger有幾個misfire相關的策略,告訴quartz當misfire發(fā)生的時候應該如何處理。這些策略以常量的形式在SimpleTrigger中定義(JavaDoc中介紹了它們的功能)。這些策略包括:
SimpleTrigger的Misfire策略常量:
MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY MISFIRE_INSTRUCTION_FIRE_NOW MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT
CronTrigger
CronTrigger通常比Simple Trigger更有用,如果您需要基于日歷的概念而不是按照SimpleTrigger的精確指定間隔進行重新啟動的作業(yè)啟動計劃。
使用CronTrigger,您可以指定號時間表,例如“每周五中午”或“每個工作日和上午9:30”,甚至“每周一至周五上午9:00至10點之間每5分鐘”和1月份的星期五“。
即使如此,和SimpleTrigger一樣,CronTrigger有一個startTime,它指定何時生效,以及一個(可選的)endTime,用于指定何時停止計劃。
Cron Expressions
Cron-Expressions用于配置CronTrigger的實例。Cron Expressions是由七個子表達式組成的字符串,用于描述日程表的各個細節(jié)。這些子表達式用空格分隔,并表示:
- Seconds
- Minutes
- Hours
- Day-of-Month
- Month
- Day-of-Week
- Year (optional field)
一個完整的Cron-Expressions的例子是字符串“0 0 12?* WED“ - 這意味著”每個星期三下午12:00“。
單個子表達式可以包含范圍和/或列表。例如,可以用“MON-FRI”,“MON,WED,F(xiàn)RI”或甚至“MON-WED,SAT”代替前一個(例如“WED”)示例中的星期幾字段。
通配符(’ '字符)可用于說明該字段的“每個”可能的值。因此,前一個例子的“月”字段中的“”字符僅僅是“每個月”。因此,“星期幾”字段中的“*”顯然意味著“每周的每一天”。
所有字段都有一組可以指定的有效值。這些值應該是相當明顯的 - 例如秒和分鐘的數(shù)字0到59,數(shù)小時的值0到23。日期可以是1-31的任何值,但是您需要注意在給定的月份中有多少天!月份可以指定為0到11之間的值,或者使用字符串JAN,F(xiàn)EB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV和DEC。星期幾可以指定為1到7(1 =星期日)之間的值,或者使用字符串SUN,MON,TUE,WED,THU,F(xiàn)RI和SAT。
'/'字符可用于指定值的增量。例如,如果在“分鐘”字段中輸入“0/15”,則表示“每隔15分鐘,從零開始”。如果您在“分鐘”字段中使用“3/20”,則意味著“每隔20分鐘,從三分鐘開始” - 換句話說,它與“分鐘”中的“3,23,43”相同領域。請注意“ / 35”的細微之處并不代表“每35分鐘” - 這意味著“每隔35分鐘,從零開始” - 或者換句話說,與指定“0,35”相同。
‘?’ 字符是允許的日期和星期幾字段。用于指定“無特定值”。當您需要在兩個字段中的一個字段中指定某個字符而不是另一個字段時,這很有用。請參閱下面的示例(和CronTrigger JavaDoc)以進行說明。
“L”字符允許用于月日和星期幾字段。這個角色對于“最后”來說是短暫的,但是在這兩個領域的每一個領域都有不同的含義。例如,“月”字段中的“L”表示“月的最后一天” - 1月31日,非閏年2月28日。如果在本周的某一天使用,它只是意味著“7”或“SAT”。但是如果在星期幾的領域中再次使用這個值,就意味著“最后一個月的xxx日”,例如“6L”或“FRIL”都意味著“月的最后一個星期五”。您還可以指定從該月最后一天的偏移量,例如“L-3”,這意味著日歷月份的第三個到最后一天。當使用’L’選項時,重要的是不要指定列表或值的范圍,因為您會得到混亂/意外的結果。
“W”用于指定最近給定日期的工作日(星期一至星期五)。例如,如果要將“15W”指定為月日期字段的值,則意思是:“最近的平日到當月15日”。
'#'用于指定本月的“第n個”XXX工作日。例如,“星期幾”字段中的“6#3”或“FRI#3”的值表示“本月的第三個星期五”。
Cron Expressions示例
CronTrigger示例1 - 創(chuàng)建一個觸發(fā)器的表達式,每5分鐘就會觸發(fā)一次
0 0/5 * * *?
CronTrigger示例2 - 創(chuàng)建觸發(fā)器的表達式,每5分鐘觸發(fā)一次,分鐘后10秒(即上午10時10分,上午10:05:10等)。
10 0/5 * * *?
CronTrigger示例3 - 在每個星期三和星期五的10:30,11:30,12:30和13:30創(chuàng)建觸發(fā)器的表達式。
0 30 10-13?* WED,F(xiàn)RI
CronTrigger示例4 - 創(chuàng)建觸發(fā)器的表達式,每個月5日和20日上午8點至10點之間每半小時觸發(fā)一次。請注意,觸發(fā)器將不會在上午10點開始,僅在8:00,8:30,9:00和9:30
0 0/30 8-9 5,20 *?
請注意,一些調度要求太復雜,無法用單一觸發(fā)表示 - 例如“每上午9:00至10:00之間每5分鐘,下午1:00至晚上10點之間每20分鐘”一次。在這種情況下的解決方案是簡單地創(chuàng)建兩個觸發(fā)器,并注冊它們來運行相同的作業(yè)。
構建CronTriggers
建立一個觸發(fā)器,每隔兩分鐘,每天上午8點至下午5點之間:
trigger = newTrigger()
.withIdentity("trigger3", "group1")
.withSchedule(cronSchedule("0 0/2 8-17 * * ?"))
.forJob("myJob", "group1")
.build();
建立一個觸發(fā)器,將在上午10:42每天發(fā)射:
trigger = newTrigger()
.withIdentity("trigger3", "group1")
.withSchedule(dailyAtHourAndMinute(10, 42))
.forJob(myJobKey)
.build();
trigger = newTrigger()
.withIdentity("trigger3", "group1")
.withSchedule(cronSchedule("0 42 10 * * ?"))
.forJob(myJobKey)
.build();
建立一個觸發(fā)器,將在星期三上午10:42在TimeZone(系統(tǒng)默認值)之外觸發(fā):
trigger = newTrigger()
.withIdentity("trigger3", "group1")
.withSchedule(weeklyOnDayAndHourAndMinute(DateBuilder.WEDNESDAY, 10, 42))
.forJob(myJobKey)
.inTimeZone(TimeZone.getTimeZone("America/Los_Angeles"))
.build();
trigger = newTrigger()
.withIdentity("trigger3", "group1")
.withSchedule(cronSchedule("0 42 10 ? * WED"))
.inTimeZone(TimeZone.getTimeZone("America/Los_Angeles"))
.forJob(myJobKey)
.build();
CronTrigger Misfire說明
CronTrigger本身的常量(包括描述其行為的JavaDoc)。說明包括:
CronTrigger的Misfire指令常數(shù)
MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY MISFIRE_INSTRUCTION_DO_NOTHING MISFIRE_INSTRUCTION_FIRE_NOW
到此這篇關于Java框架Quartz中的Trigger簡析的文章就介紹到這了,更多相關Quartz中的Trigger內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Spring?Boot?整合?Smart-Doc的詳細過程(零注解生成?API?文檔,告別?Swagger)
本文將詳細介紹如何在SpringBoot項目中整合Smart-Doc,以及使用Maven插件一鍵生成多種格式的API文檔,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2025-06-06
mybatis-plus雪花算法增強idworker的實現(xiàn)
今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,進一步增強實現(xiàn)生成分布式唯一ID,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-07-07
spring boot整合Shiro實現(xiàn)單點登錄的示例代碼
本篇文章主要介紹了spring boot整合Shiro實現(xiàn)單點登錄的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01
SpringBoot + Mybatis增刪改查實戰(zhàn)記錄
這篇文章主要給大家介紹了關于SpringBoot + Mybatis增刪改查的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧2019-05-05
如何使用 Spring Boot 和 Canal 實現(xiàn) My
本文介紹了如何使用SpringBoot和Canal實現(xiàn)MySQL數(shù)據(jù)庫之間的數(shù)據(jù)同步,通過配置主庫、創(chuàng)建Canal用戶、配置CanalServer以及開發(fā)SpringBoot客戶端,實現(xiàn)了將主庫的數(shù)據(jù)實時同步到多個從庫,感興趣的朋友跟隨小編一起看看吧2025-02-02
java結合keytool如何實現(xiàn)非對稱加密與解密詳解
這篇文章主要給大家介紹了關于java結合keytool如何實現(xiàn)非對稱加密與解密的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友下面隨著小編來一起學習學習吧2018-08-08
Spring Boot集成Seata實現(xiàn)基于AT模式的分布式事務的解決方案
Seata 是一款開源的分布式事務解決方案,致力于提供高性能和簡單易用的分布式事務服務,這篇文章主要介紹了Spring Boot集成Seata實現(xiàn)基于AT模式的分布式事務,需要的朋友可以參考下2024-08-08

