閱讀931 返回首頁    go 阿裏雲 go 技術社區[雲棲]


Quartz教程四:Trigger

本係列教程由quartz-2.2.x官方文檔翻譯、整理而來,希望給同樣對quartz感興趣的朋友一些參考和幫助,有任何不當或錯誤之處,歡迎指正;有興趣研究源碼的同學,可以參考我對quartz-core源碼的注釋(進行中)

與job一樣,trigger也很容易使用,但是還有一些擴展選項需要理解,以便更好地使用quartz。trigger也有很多類型,可以根據實際需要來選擇。

最常用的兩種trigger會分別在教程五:SimpleTrigger教程六:CronTrigger中講到;

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是7月1號,則其最後一次執行時間是6月5號。

其它的屬性,會在下麵的小節中解釋。

優先級(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的實現,根據需要進行選擇。

最後更新:2017-05-23 16:33:56

  上一篇:go  Java 8: Lambdas, Part 1
  下一篇:go  華爾街失守:摩根大通家的AI將36萬小時的工作縮至秒級