jobDataMap能夠用來裝載可序列化的對象
,用於在job執行的時候獲取。html
注:jobDetail
和trigger
中均可以添加jobDataMap,後面的對象會把前面對象相同鍵值對象的值覆蓋
。java
job實體類建立代碼(建立job示例,添加jobDataMap)api
public static void main(String[] args) throws SchedulerException, ParseException { SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); scheduler.start(); // 定義job,綁定咱們的定時任務 JobDetail job2 = newJob(HelloJob.class) .usingJobData("name", "李四") .usingJobData("characteristic", "22") .build(); // 執行任務,用定義好的觸發器 和 任務 scheduler.scheduleJob(job2, getTrigger1()); }
job類代碼(job運行示例,獲取jobDataMap)服務器
public void execute(JobExecutionContext context) throws JobExecutionException { JobDataMap jobDataMap = context.getJobDetail().getJobDataMap(); String name = jobDataMap.get("name").toString(); String characteristic = jobDataMap.get("characteristic").toString(); JobDataMap mergedJobDataMap = context.getMergedJobDataMap(); String mergedName = mergedJobDataMap.getString("name"); System.out.println("name : " + name); System.out.println("mergedName:" + mergedName); System.out.println("characteristic : " + characteristic); }
trigger併發
/** * 觸發器當即觸發,而後每隔2秒 觸發一次,22:55:00: */ private static SimpleTrigger getTrigger1() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); //定義一個任務觸發器 return TriggerBuilder.newTrigger() .withIdentity("job2", "group2") //定點觸發 //.startAt(sdf.parse("2018-09-27 10:27:00")) // 五秒鐘後觸發 .startAt(DateBuilder.futureDate(5, DateBuilder.IntervalUnit.SECOND)) .withSchedule( simpleSchedule() .withIntervalInSeconds(2) .repeatForever() //.withRepeatCount(0) ) .usingJobData("name",",,") //.endAt(DateBuilder.dateOf(22, 55, 0)) .build(); }
測試結果:測試
name : 李四 mergedName:,, characteristic : 22
trigger是觸發器,任務什麼時候運行、運行幾回
,它說了算。ui
設置TriggerKey能夠經過JobBuilder的.withIdentity()
進行設置,以下:默認api提供三種方式 <img src="https://ws3.sinaimg.cn/mw690/005AQjvJly1fw41dc8fvjj30s608wq4z.jpg" alt="image">this
全參數的源碼以下:code
public TriggerBuilder<T> withIdentity(String name, String group) { key = new TriggerKey(name, group); return this; }
注:name屬性是必填的,group不寫,默認值爲:default
orm
JobKey大同小異,不予介紹。
使用場景:在一個指定時間段內執行一次做業任務
或是在指定的時間間隔內屢次執行做業任務
,SimpleTrigger應該能知足你的調度需求。
例如:
private static SimpleTrigger getTrigger2() throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); //定義一個任務觸發器 return newTrigger() .withIdentity("job1", "group1") //定點觸發 .startAt(sdf.parse("2018-09-27 10:27:00")) .withSchedule(simpleSchedule() .withIntervalInSeconds(2) .withRepeatCount(0) ).build(); }
注:startAt中的日期可使用DateBuilder,示例,在指定時間延遲5秒執行
.startAt(DateBuilder.futureDate(5, DateBuilder.IntervalUnit.SECOND))
執行常量以下:
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
觸發指令設置
withMisfireHandlingInstructionFireNow ——以當前時間爲觸發頻率當即觸發執行 ——執行至FinalTIme的剩餘週期次數 ——以調度或恢復調度的時刻爲基準的週期頻率,FinalTime根據剩餘次數和當前時間計算獲得 ——調整後的FinalTime會略大於根據starttime計算的到的FinalTime值 withMisfireHandlingInstructionIgnoreMisfires ——以錯過的第一個頻率時間馬上開始執行 ——重作錯過的全部頻率週期 ——當下一次觸發頻率發生時間大於當前時間之後,按照Interval的依次執行剩下的頻率 ——共執行RepeatCount+1次 withMisfireHandlingInstructionNextWithExistingCount ——不觸發當即執行 ——等待下次觸發頻率週期時刻,執行至FinalTime的剩餘週期次數 ——以startTime爲基準計算週期頻率,並獲得FinalTime ——即便中間出現pause,resume之後保持FinalTime時間不變 withMisfireHandlingInstructionNowWithExistingCount ——以當前時間爲觸發頻率當即觸發執行 ——執行至FinalTIme的剩餘週期次數 ——以調度或恢復調度的時刻爲基準的週期頻率,FinalTime根據剩餘次數和當前時間計算獲得 ——調整後的FinalTime會略大於根據starttime計算的到的FinalTime值 withMisfireHandlingInstructionNextWithRemainingCount ——不觸發當即執行 ——等待下次觸發頻率週期時刻,執行至FinalTime的剩餘週期次數 ——以startTime爲基準計算週期頻率,並獲得FinalTime ——即便中間出現pause,resume之後保持FinalTime時間不變 withMisfireHandlingInstructionNowWithRemainingCount ——以當前時間爲觸發頻率當即觸發執行 ——執行至FinalTIme的剩餘週期次數 ——以調度或恢復調度的時刻爲基準的週期頻率,FinalTime根據剩餘次數和當前時間計算獲得 ——調整後的FinalTime會略大於根據starttime計算的到的FinalTime值 MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT ——此指令致使trigger忘記原始設置的starttime和repeat-count ——觸發器的repeat-count將被設置爲剩餘的次數 ——這樣會致使後面沒法得到原始設定的starttime和repeat-count值
使用場景:CronTrigger比SimpleTrigger更經常使用,當你須要一個基於日曆般概念的做業調度器,而不是像SimpleTrigger那樣精確指定間隔時間。
使用cronTrigger,你能夠這樣指定觸發時間表例如每週五的中午
,或是每週末的上午9:30
,甚至是一月份每週1、3、五上午9:00到10:00之間每5分鐘
。
CronTrigger也須要指定startTime讓調度器生效,指定endTime讓調度器終止。
Cron表達式其實是由7個子表達式組成的字符串,這些子表達式用空格隔開,分別表明:
類型 | 範圍 |
---|---|
秒 | 0-60 |
分 | 0-60 |
小時 | 0-23 |
月份中的天數 | 0-31,但須要注意,有些月份如沒有31 |
月 | 0-11,可使用:JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC |
星期中的天數 | 1-7,可使用: SUN,MON,TUE,WED,THU,FRI,SAT |
年(可選) | 通常不用 |
/ : - 若是你在分鐘字段寫「0/15」,這表示「每次從一小時中的第0分鐘開始,每隔15分鐘觸發」, - 若是你在分鐘字段上寫「3/20」,這表示「每次從一小時中的第3分鐘開始,每隔20分鐘觸發」——換句話說,這跟在分鐘字段上指定「3,23,43」是同樣的。
? : - 字符容許出如今月份中的天數和星期中的天數字段中。它通常用來指定「不關心的值」。 - 當你須要在這兩個字段中的一個指定不肯定的值是很是方便的,這個字符不能用在其餘的字段中。
L : - 字符容許出如今月份中的天數和星期中的天數字段中 - 「L」字符出如今月份中的天數字段中表示「每個月的最後一天」——1月31日,平年的2月28日
w : - 字符用來指定給定日期的最近一個工做日(工做日指的是從週一到週五) - 若是你在月份中的天數字段的值指定爲「15w」,這表示「離每個月15號最近的工做日」。
'井' : - 」字符用來指定每個月的第N個工做日 - 星期中的天數字段的值爲「6#3」或是「FRI#3」表示「每個月的第三個星期五」。
Cron案例1——僅僅表示每隔5分鐘觸發一次:"0 0/5 * * * ?"
Cron案例2——表示每隔5分鐘,在過了10秒後觸發一次(例如上午10:00:10,10:05:10等):"10 0/5 * * * ?"
Cron案例3——表示每一個週三到週五,在上午10:30,11:30,12:30和13:30分觸發:"0 30 10-13 ? * WED,FRI"
Cron案例4——表示每個月從5號到20號,上午8時到10時之間的每半小時觸發,注意這個觸發器只在8:00,8:30,9:00和9:30分觸發,上午10:00不會觸發:"0 0/30 8-9 5,20 * ?"
注意有些調度需求因太複雜例如「上午9:00到10:00之間的每5分鐘,下午1:00到10:00的每20分鐘」,而不能用單一的觸發器來表示。這種狀況的解決方案是建立兩個簡單的觸發器,將它們註冊到調度器中去運行同一個做業任務。
觸發器,天天從的下午3:33 觸發一次
private static CronTrigger getTrigger5() throws ParseException { //定義一個任務觸發器 return newTrigger() .withIdentity("job1", "group1") .withSchedule(CronScheduleBuilder.cronSchedule("0 27 16 * * ?")) //或者下邊這樣寫 // .withSchedule(CronScheduleBuilder.dailyAtHourAndMinute(15, 33)) .forJob("job1", "group1") .build(); }
注:CronScheduleBuilder默認提供了一些經常使用表達式實現,以下圖,請自行嘗試
<img src="https://ws2.sinaimg.cn/mw690/005AQjvJly1fw440fu2jnj31dw0fowkp.jpg" alt="image">
CronTrigger的觸發失敗指令常量:
MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY MISFIRE_INSTRUCTION_DO_NOTHING MISFIRE_INSTRUCTION_FIRE_NOW
觸發指令設置:
withMisfireHandlingInstructionDoNothing ——不觸發當即執行 ——等待下次Cron觸發頻率到達時刻開始按照Cron頻率依次執行 withMisfireHandlingInstructionIgnoreMisfires ——以錯過的第一個頻率時間馬上開始執行 ——重作錯過的全部頻率週期後 ——當下一次觸發頻率發生時間大於當前時間後,再按照正常的Cron頻率依次執行 withMisfireHandlingInstructionFireAndProceed ——以當前時間爲觸發頻率馬上觸發一次執行 ——而後按照Cron頻率依次執行
補全問題
問題介紹: - 1).執行暫停任務,重啓後,在暫停期間沒執行的任務又TM給補上了 - 2).服務器掛了,重啓後,在暫停期間沒執行的任務又TM給補上了
解決方式:
cronSchedule(cronExpression).withMisfireHandlingInstructionFireAndProceed() 或者 cronSchedule(cronExpression).withMisfireHandlingInstructionDoNothing()
設置完成從新啓動發現沒軟用
#這個時間大於10000(10秒)會致使MISFIRE_INSTRUCTION_DO_NOTHING不起做用。 org.quartz.jobStore.misfireThreshold = 5000
解釋:
misfireThreshold表示實際執行的時間與下一次應該執行時間之間的差值,超過這個差值就不會執行,低於這個差值就會執行。 好比我每3秒執行一次,misfireThreshold=6000,當你暫停低於6秒內,它會彌補執行,超過6秒,它就再也不彌補執行了。
(quartz暫停及恢復任務解決恢復時一咕嚕把未執行的全補回來的問題)[http://www.itboth.com/d/mqE3In/quartz-java]<br> (quartz 失敗觸發指令)[http://www.voidcn.com/article/p-yvvrqdrt-ku.html]<br>