Quartz使用(3) - Quartz核心接口Trigger


Trigger最常用的有兩種SimpleTrigger和CronTrigger,首先介紹Trigger的一些基礎的信息,然后會詳細描述這兩種Trigger。

1. 通用Trigger屬性

quartz中所有的觸發器Trigger都有一些共有屬性,如TriggerKey,startTime等,這些屬性可以使用TriggerBuilder進行設置。常用的屬性舉例如下:

(1) triggerKey:觸發器的標識,由名稱與分組唯一指定,便於調度器調用與查找。

(2) jobKey: 當觸發器被觸發時,標識哪一個任務Job應該被執行。

(3) startTime: 表示觸發器第一次開始觸發的時間。

(4) endTime: 表示觸發器終止觸發的時間。

2. 優先級

當存在多個觸發器時,quartz可能沒有足夠的資源立即觸發所有配置為同一時間觸發的triggers,因此可以設置每個Trigger的優先級。默認的優先級為5,可取任意的整型值,包括正數或負數。注意優先級僅用於所有相同時間觸發的triggers

3. 未啟動指令"Misfire  Instructions"

Trigger未觸發一般產生於調度器被關閉,或線程池不足時。不同的Trigger類型有不同的未啟動指令。默認的,他們會使用"smart policy"指定。這些指令的使用場景在於,當scheduler開啟時,它將搜索所有未啟動的持久化的觸發器,然后基於觸發器各自配置"未啟動指令"來更新觸發器。未啟動指令用於當trigger未正常觸發時,是否恢復執行的場景。

4. Calendars

與Trigger關聯的Calendar對象,用於在指定的時間內不觸發trigger,例如你有一個任務每天執行一次,但你不希望在節假日執行時,Calendar此時派上用場。注意此Calendar為quartz自身的定義接口,而非Java自帶的Calendar。

Calendar需要在Scheduler定義過程中,通過scheduler.addCalendar()進行初始化和注冊。

示例:

import static org.quartz.JobBuilder.*;
import static org.quartz.TriggerBuilder.*;
import static org.quartz.SimpleScheduleBuilder.*;
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
View Code

 5. SimpleTrigger

 當需要在規定時間執行一次或在規定的時間段以一定的時間間隔重復觸發執行Job時,SimpleTrigger就可以滿足。

SimpleTrigger的屬性有:開始時間、結束時間、重復次數和重復的時間間隔。重復次數屬性的值可以為0、正整數、或常量 SimpleTrigger.REPEAT_INDEFINITELY,重復的時間間隔屬性值必須為0或長整型的正整數,以毫秒作為時間單位,當重復的時間間隔為0時,意味着與Trigger同時觸發執行。如果有指定結束時間屬性值,則結束時間屬性優先於重復次數屬性,這樣的好處在於:當我們需要創建一個每間隔10秒鍾觸發一次直到指定的結束時間的 Trigger,而無需去計算從開始到結束的所重復的次數,我們只需簡單的指定結束時間和使用REPEAT_INDEFINITELY作為重復次數的屬性 值即可。

 示例:

(1) 創建在特定時間觸發,非重復的Trigger

import static org.quartz.TriggerBuilder.*;
import static org.quartz.SimpleScheduleBuilder.*;
import static org.quartz.DateBuilder.*:
SimpleTrigger trigger = (SimpleTrigger) newTrigger()
    .withIdentity("trigger1", "group1")
    .startAt(myStartTime) // some Date
    .forJob("job1", "group1") // identify job with name, group strings
    .build();
View Code

(2) 創建在特定時間觸發,重復間隔為10次,重復執行10次的Trigger

import static org.quartz.TriggerBuilder.*;
import static org.quartz.SimpleScheduleBuilder.*;
import static org.quartz.DateBuilder.*:
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();
View Code

(3) 創建5分鍾后執行,且觸發一次的Trigger

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();
View Code

(4) 創建立即執行,且重復間隔為5分鍾,到22點結束的Trigger

trigger = newTrigger()
    .withIdentity("trigger7", "group1")
    .withSchedule(simpleSchedule()
        .withIntervalInMinutes(5)
        .repeatForever())
    .endAt(dateOf(22, 0, 0))
    .build();
View Code

(5) 創建在下一小時觸發,且每2小時執行重復執行的Trigger

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);
View Code

SimpleTrigger的未啟動指令包含如下:

MISFIRE_INSTRUCTION_SMART_POLICY
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

構件SimpleTrigger的時候,可以指定Trigger的未啟動指令:

trigger = newTrigger()
    .withIdentity("trigger7", "group1")
    .withSchedule(simpleSchedule()
        .withIntervalInMinutes(5)
        .repeatForever()
        .withMisfireHandlingInstructionNextWithExistingCount())
    .build();
View Code

 

6. CronTrigger 

6.1 cron表達式

CronTrigger 支持比SimpleTrigger更具體、更復雜的調度。基於cron表達式,CronTrigger支持類似日歷的重復間隔,而非單一的時間間隔。

序號 說明 是否必填 允許填寫的值 允許的通配符
1 0-59 , - * /
2 0-59 , - * /
3 小時 0-23 , - * /
4 1-31  , - * ? / L W
5 1-12或JAN-DEC , - * /
6 1-7或SUN-SAT , - * ? / L #
7 空或1999-2017 , - * /

通配符的說明:

(1) 反斜線(/)字符表示增量值。例如,在秒字段中“5/15”代表從第 5 秒開始,每 15 秒一次。

(2) 星號(*)字符是通配字符,表示該字段可以接受任何可能的值,例如:在分的字段上設置 "*",表示每一分鍾都會觸發。

(3) 問號(?)問號表示這個字段不包含具體值。如果指定月內日期,可以在月內日期字段中插入“?”,表示周內日期值無關緊要。

(4) -  表示區間,例如 在小時上設置 "10-12",表示 10,11,12點都會觸發。

(5) 逗號(, ) 表示指定多個值,例如在周字段上設置 "MON,WED,FRI" 表示周一,周三和周五觸發。

(6) 井號(#)字符為給定月份指定具體的工作日實例。把“MON#2”放在周內日期字段中,表示把任務安排在當月的第二個星期一。

(7) L 表示最后的意思。在日字段設置上,表示當月的最后一天(依據當前月份,如果是二月還會依據是否是潤年[leap]), 在周字段上表示星期六,相當於"7"或"SAT"。如果在"L"前加上數字,則表示該數據的最后一個。例如在周字段上設置"6L"這樣的格式,則表示“本月最后一個星期五"。

(8) W 表示離指定日期的最近那個工作日(周一至周五). 例如在日字段上設置"15W",表示離每月15號最近的那個工作日觸發。如果15號正好是周六,則找最近的周五(14號)觸發, 如果15號是周未,則找最近的下周一(16號)觸發.如果15號正好在工作日(周一至周五),則就在該天觸發。如果指定格式為 "1W",它則表示每月1號往后最近的工作日觸發。如果1號正是周六,則將在3號下周一觸發。(注,"W"前只能設置具體的數字,不允許區間"-")。

注:'L'和 'W'可以組合使用。如果在日字段上設置"LW",則表示在本月的最后一個工作日觸發。

cron表達式的舉例如下:

0 10 * * * ?--------------每個小時過10分執行一次
0 0/32 8,12 * * ? ----------每天8:32,12:32 執行一次
0 0/2 * * * ?--------------每2分鍾執行一次
0 0 12 * * ?---------------在每天中午12:00觸發 
0 15 10 ? * *---------------每天上午10:15 觸發 
0 15 10 * * ?---------------每天上午10:15 觸發 
0 15 10 * * ? *---------------每天上午10:15 觸發 
0 15 10 * * ? 2005---------------在2005年中的每天上午10:15 觸發 
0 * 14 * * ?---------------每天在下午2:00至2:59之間每分鍾觸發一次 
0 0/5 14 * * ?---------------每天在下午2:00至2:59之間每5分鍾觸發一次 
0 0/5 14,18 * * ?---------------每天在下午2:00至2:59和6:00至6:59之間的每5分鍾觸發一次 
0 0-5 14 * * ?---------------每天在下午2:00至2:05之間每分鍾觸發一次 
0 10,44 14 ? 3 WED---------------每三月份的星期三在下午2:00和2:44時觸發 
0 15 10 ? * MON-FRI---------------從星期一至星期五的每天上午10:15觸發 
0 15 10 15 * ?---------------在每個月的每15天的上午10:15觸發 
0 15 10 L * ?---------------在每個月的最后一天的上午10:15觸發 
0 15 10 ? * 6L---------------在每個月的最后一個星期五的上午10:15觸發 
0 15 10 ? * 6L 2002-2005---------------在2002, 2003, 2004 and 2005年的每個月的最后一個星期五的上午10:15觸發 
0 15 10 ? * 6#3---------------在每個月的第三個星期五的上午10:15觸發 
0 0 12 1/5 * ?---------------從每月的第一天起每過5天的中午12:00時觸發 
0 11 11 11 11 ?---------------在每個11月11日的上午11:11時觸發
View Code

6.2 CronTrigger構建

可以使用TriggerBuilder 來定義CronTrigger對象。示例如下:

import static org.quartz.TriggerBuilder.*;
import static org.quartz.CronScheduleBuilder.*;
import static org.quartz.DateBuilder.*:

trigger = newTrigger()
    .withIdentity("trigger3", "group1")
    .withSchedule(cronSchedule("0 0/2 8-17 * * ?"))
    .forJob("myJob", "group1")
    .build();
    
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();
    
trigger = newTrigger()
    .withIdentity("trigger3", "group1")
    .withSchedule(weeklyOnDayAndHourAndMinute(DateBuilder.WEDNESDAY, 10, 42))
    .forJob(myJobKey)
    .inTimeZone(TimeZone.getTimeZone("Asia/Shanghai"))
    .build();

trigger = newTrigger()
    .withIdentity("trigger3", "group1")
    .withSchedule(cronSchedule("0 42 10 ? * WED"))
    .inTimeZone(TimeZone.getTimeZone("Asia/Shanghai"))
    .forJob(myJobKey)
    .build();    
View Code

6.3 CronTrigger Misfire Instruction

CronTrigger的未啟動指令包含:

MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY
MISFIRE_INSTRUCTION_DO_NOTHING
MISFIRE_INSTRUCTION_FIRE_NOW
MISFIRE_INSTRUCTION_SMART_POLICY

未啟動指令的使用:

trigger = newTrigger()
    .withIdentity("trigger3", "group1")
    .withSchedule(cronSchedule("0 0/2 8-17 * * ?")
        .withMisfireHandlingInstructionFireAndProceed())
    .forJob("myJob", "group1")
    .build();
View Code


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM