Quartz教程四:Trigger
本系列教程由quartz-2.2.x官方文件翻譯、整理而來,希望給同樣對quartz感興趣的朋友一些參考和幫助,有任何不當或錯誤之處,歡迎指正;有興趣研究原始碼的同學,可以參考我對quartz-core原始碼的註釋(進行中)。
與job一樣,trigger也很容易使用,但是還有一些擴充套件選項需要理解,以便更好地使用quartz。trigger也有很多型別,可以根據實際需要來選擇。
Trigger的公共屬性
所有型別的trigger都有TriggerKey這個屬性,表示trigger的身份;除此之外,trigger還有很多其它的公共屬性。這些屬性,在構建trigger的時候可以通過TriggerBuilder設定。
trigger的公共屬性有:
jobKey
屬性:當trigger觸發時被執行的job的身份;startTime
屬性:設定trigger第一次觸發的時間;該屬性的值是java.util.Date型別,表示某個指定的時間點;有些型別的trigger,會在設定的startTime
時立即觸發,有些型別的trigger,表示其觸發是在startTime
之後開始生效。比如,現在是1月份,你設定了一個trigger–“在每個月的第5天執行”,然後你將startTime
屬性設定為4月1號,則該trigger第一次觸發會是在幾個月以後了(即4月5號)。endTime
屬性:表示trigger失效的時間點。比如,”每月第5天執行”的trigger,如果其endTime
其它的屬性,會在下面的小節中解釋。
優先順序(priority)
如果你的trigger很多(或者Quartz執行緒池的工作執行緒太少),Quartz可能沒有足夠的資源同時觸發所有的trigger;這種情況下,你可能希望控制哪些trigger優先使用Quartz的工作執行緒,要達到該目的,可以在trigger上設定priority
屬性。比如,你有N個trigger需要同時觸發,但只有Z個工作執行緒,優先順序最高的Z個trigger會被首先觸發。如果沒有為trigger設定優先順序,trigger使用預設優先順序,值為5;priority
屬性的值可以是任意整數,正數、負數都可以。
注意:只有同時觸發的trigger之間才會比較優先順序。10:59觸發的trigger總是在11:00觸發的trigger之前執行。
注意:如果trigger是可恢復的,在恢復後再排程時,優先順序與原trigger是一樣的。
錯過觸發(misfire)
trigger還有一個重要的屬性misfire;如果scheduler關閉了,或者Quartz執行緒池中沒有可用的執行緒來執行job,此時永續性的trigger就會錯過(miss)其觸發時間,即錯過觸發(misfire)。不同型別的trigger,有不同的misfire機制。它們預設都使用“智慧機制(smart policy)”,即根據trigger的型別和配置動態調整行為。當scheduler啟動的時候,查詢所有錯過觸發(misfire)的永續性trigger。然後根據它們各自的misfire機制更新trigger的資訊。當你在專案中使用Quartz時,你應該對各種型別的trigger的misfire機制都比較熟悉,這些misfire機制在JavaDoc中有說明。關於misfire機制的細節,會在講到具體的trigger時作介紹。
日曆(calendar)
Quartz的Calendar物件(不是java.util.Calendar物件)可以在定義和儲存trigger的時候與trigger進行關聯。Calendar用於從trigger的排程計劃中排除時間段。比如,可以建立一個trigger,每個工作日的上午9:30執行,然後增加一個Calendar,排除掉所有的商業節日。
任何實現了Calendar介面的可序列化物件都可以作為Calendar物件,Calendar介面如下:
package org.quartz;
public interface Calendar {
public boolean isTimeIncluded(long timeStamp);
public long getNextIncludedTime(long timeStamp);
}
注意到這些方法的引數型別為long。你也許猜到了,他們就是毫秒單位的時間戳。即Calendar排除時間段的單位可以精確到毫秒。你也許對“排除一整天”的Calendar比較感興趣。Quartz提供的org.quartz.impl.HolidayCalendar類可以很方便地實現。
Calendar必須先例項化,然後通過addCalendar()方法註冊到scheduler。如果使用HolidayCalendar,例項化後,需要呼叫addExcludedDate(Date date)方法從排程計劃中排除時間段。以下示例是將同一個Calendar例項用於多個trigger:
HolidayCalendar cal = new HolidayCalendar();
cal.addExcludedDate( someDate );
cal.addExcludedDate( someOtherDate );
sched.addCalendar("myHolidays", cal, false);
Trigger t = newTrigger()
.withIdentity("myTrigger")
.forJob("myJob")
.withSchedule(dailyAtHourAndMinute(9, 30)) // execute job daily at 9:30
.modifiedByCalendar("myHolidays") // but not on holidays
.build();
// .. schedule job with trigger
Trigger t2 = newTrigger()
.withIdentity("myTrigger2")
.forJob("myJob2")
.withSchedule(dailyAtHourAndMinute(11, 30)) // execute job daily at 11:30
.modifiedByCalendar("myHolidays") // but not on holidays
.build();
// .. schedule job with trigger2
構造trigger的細節將在接下來的幾節中講到。就現在,只需要知道上面的程式碼建立了兩個trigger,都是每天執行一次。但是在Calendar定義的時間段內,trigger的執行被跳過。
org.quartz.impl.calendar包下有各種Calendar的實現,根據需要進行選擇。