Quartz 定時任務(wù)使用

官方文檔

1. 使用quartz

在開始使用scheduler前厂财,首先使用SchedulerFactory創(chuàng)建一個

SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();

  Scheduler sched = schedFact.getScheduler();

  sched.start();

  // define the job and tie it to our HelloJob class
  JobDetail job = newJob(HelloJob.class)
      .withIdentity("myJob", "group1")
      .build();

  // Trigger the job to run now, and then every 40 seconds
  Trigger trigger = newTrigger()
      .withIdentity("myTrigger", "group1")
      .startNow()
      .withSchedule(simpleSchedule()
          .withIntervalInSeconds(40)
          .repeatForever())
      .build();

  // Tell quartz to schedule the job using our trigger
  sched.scheduleJob(job, trigger);

2. Quartz Api jobs 和 trigger

2.1 Quartz Api
  • [x] Scheduler
  • [x] Job
  • [x] JobDetail
  • [x] Trigger
  • [x] JobBuilder
  • [x] TiggerBuilder

JobBuilder

TriggerBuilder

SimpleScheduleBulder

import static org.quartz.JobBuilder.*;
import static org.quartz.SimpleScheduleBuilder.*;
import static org.quartz.CronScheduleBuilder.*;
import static org.quartz.CalendarIntervalScheduleBuilder.*;
import static org.quartz.TriggerBuilder.*;
import static org.quartz.DateBuilder.*;

不同的ScheduleBuilder類有自己的方法定義schedules類型

比如DateBuilder類包含各種易于構(gòu)造java.util的方法熊咽。指定時間點的日期實例

2.2 Jobs and triggers
job interface

一個Job需要實現(xiàn)job 接口

package org.quartz;

  public interface Job {

    public void execute(JobExecutionContext context)
      throws JobExecutionException;
  }

當job的trigger觸發(fā)時,execute(..)方法被==scheduler’s==的一個工作線程執(zhí)行续誉。JobExecutionContext內(nèi)含有job的運行信息:執(zhí)行它的Scheduler,觸發(fā)它的Trigger,JobDetail 和其他一些items。

JobDetail對象是由Quartz客戶機(您的程序)在將作業(yè)添加到調(diào)度器時創(chuàng)建的织咧。它包含作業(yè)的各種屬性設(shè)置,以及JobDataMap漠秋,可用于存儲作業(yè)類的給定實例的狀態(tài)信息笙蒙。它本質(zhì)上是作業(yè)實例的定義,并將在下一課中進一步詳細討論庆锦。

觸發(fā)器對象用于觸發(fā)作業(yè)的執(zhí)行(或“觸發(fā)”)捅位。當您希望調(diào)度作業(yè)時,您將實例化觸發(fā)器并“優(yōu)化”其屬性,以提供您希望的調(diào)度艇搀。觸發(fā)器也可能與JobDataMap關(guān)聯(lián)——這對于將參數(shù)傳遞給特定于觸發(fā)器觸發(fā)的作業(yè)非常有用尿扯。Quartz附帶了一些不同的觸發(fā)器類型,但是最常用的類型是SimpleTrigger和CronTrigger焰雕。

如果您需要“一次性”執(zhí)行(在給定的時間點只執(zhí)行一個作業(yè))衷笋,或者需要在給定的時間點觸發(fā)一個作業(yè),并讓它重復N次矩屁,兩次執(zhí)行之間的延遲為T辟宗,那么SimpleTrigger非常有用。如果您希望基于類似日歷的時間表進行觸發(fā)吝秕,例如“每個星期五泊脐、中午”或“每個月的第10天10:15”,CronTrigger非常有用烁峭。

為什么是工作和觸發(fā)器?許多作業(yè)調(diào)度程序沒有作業(yè)和觸發(fā)器的獨立概念容客。有些人將“作業(yè)”簡單地定義為執(zhí)行時間(或調(diào)度)和一些小型作業(yè)標識符。其他的類似于Quartz的工作和觸發(fā)器對象的結(jié)合约郁。在開發(fā)Quartz時缩挑,我們認為在計劃和按照計劃執(zhí)行的工作之間創(chuàng)建一個分離是有意義的。這(在我們看來)有許多好處鬓梅。

例如调煎,作業(yè)可以獨立于觸發(fā)器創(chuàng)建和存儲在作業(yè)調(diào)度器中,而且許多觸發(fā)器可以與相同的作業(yè)關(guān)聯(lián)己肮。這種松散耦合的另一個好處是士袄,可以配置在相關(guān)觸發(fā)器過期后仍然保留在調(diào)度器中的作業(yè),以便以后可以重新調(diào)度它們谎僻,而不必重新定義它們娄柳。它還允許您修改或替換觸發(fā)器,而不必重新定義其關(guān)聯(lián)的作業(yè)艘绍。

2.3 Identities

3. more about job and trigger

使用jobbuilder

import static org.quartz.JobBuilder.*;

上一章節(jié)我們簡單的定義了一個job

// define the job and tie it to our HelloJob class
  JobDetail job = newJob(HelloJob.class)
      .withIdentity("myJob", "group1") // name "myJob", group "group1"
      .build();

  // Trigger the job to run now, and then every 40 seconds
  Trigger trigger = newTrigger()
      .withIdentity("myTrigger", "group1")
      .startNow()
      .withSchedule(simpleSchedule()
          .withIntervalInSeconds(40)
          .repeatForever())            
      .build();

  // Tell quartz to schedule the job using our trigger
  sched.scheduleJob(job, trigger);

來看一下HelloJob的定義

 public class HelloJob implements Job {

    public HelloJob() {
    }

    public void execute(JobExecutionContext context)
      throws JobExecutionException
    {
      System.err.println("Hello!  HelloJob is executing.");
    }
  }

3.1 JobDataMap

JobDataMap 可以用來存儲任意大小的數(shù)據(jù)赤拒,(在數(shù)據(jù)庫中存儲為Blob格式的數(shù)據(jù)類型),實現(xiàn)了java map并添加了常用的方法來存儲和檢索原始類型數(shù)據(jù)。

// define the job and tie it to our DumbJob class
  JobDetail job = newJob(DumbJob.class)
      .withIdentity("myJob", "group1") // name "myJob", group "group1"
      .usingJobData("jobSays", "Hello World!")
      .usingJobData("myFloatValue", 3.141f)
      .build();

在job執(zhí)行期間取出jobDataMap中的數(shù)據(jù)

public class DumbJob implements Job {

    public DumbJob() {
    }

    public void execute(JobExecutionContext context)
      throws JobExecutionException
    {
      JobKey key = context.getJobDetail().getKey();

      JobDataMap dataMap = context.getJobDetail().getJobDataMap();

      String jobSays = dataMap.getString("jobSays");
      float myFloatValue = dataMap.getFloat("myFloatValue");

      System.err.println("Instance " + key + " of DumbJob says: " + jobSays + ", and val is: " + myFloatValue);
    }
  }

JobExecutionContext’s取出merged后的jobDataMap

public class DumbJob implements Job {

    public DumbJob() {
    }

    public void execute(JobExecutionContext context)
      throws JobExecutionException
    {
      JobKey key = context.getJobDetail().getKey();

      JobDataMap dataMap = context.getMergedJobDataMap();  // Note the difference from the previous example

      String jobSays = dataMap.getString("jobSays");
      float myFloatValue = dataMap.getFloat("myFloatValue");
      ArrayList state = (ArrayList)dataMap.get("myStateData");
      state.add(new Date());

      System.err.println("Instance " + key + " of DumbJob says: " + jobSays + ", and val is: " + myFloatValue);
    }
  }
3.2 Job State and Concurrency
  • [x] @DisallowConcurrentExecution
  • [x] @PersistJobDataAfterExecution
3.3 Other Attributes Of Jobs
  • [x] Durability
  • [x] RequestsRecovery
3.4 JobExecutionException

4. More about Triggers

4.1 Common Trigger Attributes
  • [x] jobKey 標示身份
  • [x] startTime:表明trigger什么時候開始起作用诱鞠,對于一些類型的trigger來說挎挖,startTime到了就會執(zhí)行;而有一些只是簡單表明了什么時間點開始schedule航夺,比如您可以在1月份存儲一個帶有時間表的觸發(fā)器蕉朵,例如“每個月的第5天”,如果startTime屬性設(shè)置為4月1日阳掐,那么在第一次觸發(fā)之前還有幾個月的時間始衅,明白了吧冷蚂。
  • [x] endTime:表明任務(wù)執(zhí)行的截止日期,舉個栗子:一個帶有“每個月的第5天”和7月1日結(jié)束時間的觸發(fā)器將在6月5日最后一次觸發(fā)汛闸。
4.2 Priority
.withPriority(int triggerPriority)

有時蝙茶,項目中可能有許多triggers需要執(zhí)行,而你的Quartz thread pool是有限的诸老,不能保證在同一時間下所有的trigger在執(zhí)行的時候都能獲取到線程資源執(zhí)行任務(wù)隆夯,因此有時候設(shè)置priority是有必要的,優(yōu)先級越高的越先獲取到線程資源别伏。
priority需要設(shè)置為正整數(shù)蹄衷,默認為5

只有在同一時間下,priority參數(shù)才有作用畸肆,10:11的優(yōu)先級永遠比10:20的高

被恢復的任務(wù)的優(yōu)先級高于origin trigger的

4.3 Misfire Instructions

trigger 可能因為Quartz’s thread pool 沒有足夠的線程執(zhí)行trigger或因為scheduler被關(guān)閉而錯過了它的執(zhí)行時間

4.4 Calendars

此calender非java.util.Calendar

calendar對于從觸發(fā)器的觸發(fā)計劃中排除時間塊非常有用宦芦。例如宙址,您可以創(chuàng)建一個觸發(fā)器轴脐,該觸發(fā)器在每個工作日上午9:30觸發(fā)作業(yè),然后添加一個日歷抡砂,這個日歷用來排除了所有業(yè)務(wù)假期時間塊大咱。


package org.quartz;

public interface Calendar {

  public boolean isTimeIncluded(long timeStamp);

  public long getNextIncludedTime(long timeStamp);

}

注意,方法的參數(shù)都是毫秒格式的時間戳注益,意味著日歷可以“劃分”出一毫秒那么短的時間段碴巾;

Quartz的實現(xiàn)類org.quartz.impl下有豐富多樣的Calendar

AnnualCalendar 年歷

CronCalendar cron 日歷

DailyCalendar 每日日歷

HolidayCalendar 假日日歷

MonthlyCalendar 月歷

WeeklyCalendar 周歷

日歷必須通過addCalendar(..)方法實例化并注冊到調(diào)度程序丑搔。如果您使用HolidayCalendar厦瓢,在實例化它之后,需要使用它的addExcludedDate(Date Date)方法來剔除指定的時間啤月,舉個栗子:

calendar example

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

5. SimpleTrigger

如果需要在特定的時間點精確執(zhí)行job一次煮仇,或者在特定的時間點執(zhí)行job,然后在特定的時間間隔內(nèi)重復執(zhí)行job谎仲,==使用simpleTrigger==比如浙垫,你想讓trigger在2015年1月13日上午11:23:54準時fire,或者你想讓它在那個時間fire郑诺,然后每十秒鐘再fire五次夹姥。

然后你會發(fā)現(xiàn)==simpleTrigger==主要有==startTime==,==endTime==,==repeat count==,==repeat interval==這幾個屬性

repeat count 可為0,或正整數(shù)辙诞,或==SimpleTrigger.REPEAT_INDEFINITELY==

repeat interval 必須大于等于0辙售,為0可能導致重復觸發(fā)

==Quartz’s DateBuilder==便于創(chuàng)建tigger 的fire時間(在startTime和endTime內(nèi))

如果指定了endtime tigger會在startTime和endTime區(qū)間內(nèi)重復執(zhí)行job,這樣你可以自定在此區(qū)間內(nèi)執(zhí)行次數(shù)為==REPEAT_INDEFINITELY==或者設(shè)置一個比較大的執(zhí)行次數(shù)(遠遠超出endtime到來所能夠的執(zhí)行次數(shù))

使用TriggerBuilder構(gòu)建simpleTrigger


import static org.quartz.TriggerBuilder.*;
import static org.quartz.SimpleScheduleBuilder.*;
import static org.quartz.DateBuilder.*:
5.1 指定時間點執(zhí)行一次
SimpleTrigger trigger = (SimpleTrigger) newTrigger()
    .withIdentity("trigger1", "group1")
    .startAt(myStartTime) // some Date
    .forJob("job1", "group1") // identify job with name, group strings
    .build();
5.2 指定時間點開始執(zhí)行飞涂,然后沒10秒鐘執(zhí)行一次圾亏,共執(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.3 未來5分鐘執(zhí)行一次
trigger = (SimpleTrigger) newTrigger()
    .withIdentity("trigger5", "group1")
    .startAt(DateBuilder.futureDate(5, IntervalUnit.MINUTE)) // use DateBuilder to create a date in the future
    .forJob(myJobKey) // identify job with its JobKey
    .build();
5.4 現(xiàn)在開始執(zhí)行十拣,每5分鐘執(zhí)行一次一直到22:00點結(jié)束執(zhí)行
  trigger = newTrigger()
    .withIdentity("trigger7", "group1")
    .withSchedule(simpleSchedule()
        .withIntervalInMinutes(5)
        .repeatForever())
    .endAt(dateOf(22, 0, 0))
    .build();
5.5 下個小時開始時開始執(zhí)行,每2小時執(zhí)行一次志鹃,直到永遠
  trigger = newTrigger()
    .withIdentity("trigger8") // because group is not specified, "trigger8" will be in the default group
    .startAt(DateBuilder.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==和==SimpleScheduleBuilder==的可用方法

==請注意夭问,TriggerBuilder(和Quartz的其他生成器)通常會為未顯式設(shè)置的屬性選擇一個合理的值。如果不調(diào)用startAt(..)曹铃,則假定當前時間(立即)缰趋。==

5.6 SimpleTrigger Misfire Instructions

SimpleTrigger有幾個指令,可以用來通知Quartz在發(fā)生==miessFire==時應(yīng)該做什么陕见。這些指令被定義為SimpleTrigger本身上的常量

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

前面的章節(jié)已經(jīng)講述了所有的trigger都有==Trigger.MISFIRE_INSTRUCTION_SMART_POLICY==這個也是默認值

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

6. CronTrigger

CronTrigger通常比SimpleTrigger要更有用秘血,如果需要一個基于類似日歷的概念(而不是根據(jù)==SimpleTrigger==的精確指定間隔)的job觸發(fā)計劃。
使用CronTrigger评甜,您可以指定諸如“每周五中午”灰粮、“每周五和周日上午9:30”、甚至“每周一忍坷、三粘舟、五周一上午9:00到10:00之間的每5分鐘”之類的解雇時間表。

CronTrigger和SimpleTrigger一樣可以指定==startTime==和==endTime==來指定任務(wù)執(zhí)行時間區(qū)間佩研。

6.1 Cron Expressions
  • [x] Seconds
  • [x] Minutes
  • [x] Hours
  • [x] Day-of-Month
  • [x] Month
  • [x] Day-of-Week
  • [x] Year (optional field)

一個完整的cron表達式是一個字符串柑肴,比如==0 0 12 ? * WED==意味著每周三的下午12:00

單個子表達式可以包含范圍和/或列表。比如旬薯,上面的==WED==中的==DAY OF WEEK==字段可以替換為==MON-FRI==晰骑、==MON,WED==,==FRI==,甚至==MON-WED,SAT==绊序。

==DAY OF WEEK==字段中的 ==*== 顯然意味著==一周中的每一天==硕舆。

所有字段都有一組可以指定的有效值。這些值是非常符合常理的骤公。例如秒和分鐘的數(shù)值0到59抚官,小時的數(shù)值0到23。一個月的天數(shù)可以是1-31天淋样,但是你需要注意一個月有多少天!==Months==可以指定值0到11之間,或通過使用字符串==JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV and DEC==,==Days-of-Week==之間可以指定值1和7(1 =周日)或通過使用字符串的==SUN, MON, TUE, WED, THU, FRI and SAT==耗式。

字符' / '可用于指定值的增量。例如趁猴,如果在==Minutes==字段中輸入==0/15==刊咳,意思是“每隔15分鐘,從0分鐘開始”儡司。如果您在分鐘字段中使用“3/20”娱挨,它將意味著“每20分鐘,從第3分鐘開始”,換句話說捕犬,它與在分鐘字段中指定==3,23,43==相同跷坝。請注意酵镜,==/35==并不意味著==每35分鐘==,它的意思是==每個小時中的35分鐘,從0分鐘開始==柴钻,或者換句話說淮韭,與指定==0,35==相同。

==?== 字符可以用于月中的日和星期中的日字段

“L”字符可以用于月中的日期和星期中的日期字段贴届。這個字符==last==的簡寫靠粪,但是在這兩個字段中含義不同。例如毫蚓,==DAY OF MONTH== 字段中的值“L”表示“月份的最后一天” ==1月31日==占键,==非閏年2月28日==。如果單獨在==DAT OF WEEK==字段中使用元潘,它的意思就是==7==或==SAT==畔乙。但是如果用在==DAY OF WEEK==字段指定值得后面,它表示“一個月的最后一個xxx日”——例如“6L”或“FRIL”都表示“一個月的最后一個星期五”翩概。您還可以指定從該月最后一天開始的偏移量牲距,例如“L-3”,它表示日歷月的第三到最后一天氮帐。當使用“L”選項時嗅虏,需要注意不要指定列表或值的范圍洛姑,會得到混亂或意外的結(jié)果上沐。

==W==用于指定最接近給定日期的工作日(星期一至星期五)。例如楞艾,如果指定==15W==作為月份字段的值参咙,其含義是:“到本月15日最近的工作日”。

==#==用于指定每月第==n==個工作日硫眯。例如蕴侧,==6#3==或==FRI#3==在==DAY OF WEEK==字段中的值表示“一個月的第三個星期五”。

6.2 Example Cron Expressions
  • [x] ==“0 0/5 * * * ?”== 每五分鐘
  • [x] ==“0 0/5 * * * ?”== 每五分鐘后的第10秒
  • [x] ==“0 30 10-13 ? * WED,FRI”== 每周三两入、周五的10:30净宵、11:30、12:30和13:30
  • [x] ==“0 0/30 8-9 5,20 * ?”== 每月的5號至20號的8點到10點間沒隔30分鐘執(zhí)行一次裹纳,注意==trigger==不會再10:00am執(zhí)行择葡,僅會在8:00,8:30,9:00,9:30時間段執(zhí)行;
6.3 Building CronTriggers

==CronTrigger==實例可以通過==TriggerBuilder==構(gòu)建trigger的主要屬性,再通過==CronScheduleBuilder==構(gòu)建==CronTrigger==的指定屬性


import static org.quartz.TriggerBuilder.*;
import static org.quartz.CronScheduleBuilder.*;
import static org.quartz.DateBuilder.*:
6.3.1 創(chuàng)建一個trigger在每天的上午8點到下午5點每間隔2分鐘觸發(fā)一次
  trigger = newTrigger()
    .withIdentity("trigger3", "group1")
    .withSchedule(cronSchedule("0 0/2 8-17 * * ?"))
    .forJob("myJob", "group1")
    .build();
6.3.2 創(chuàng)建一個trigger在每天的上午10:42執(zhí)行一次

 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();
6.3.3 創(chuàng)建一個trigger在每周三的上午10:42執(zhí)行一次剃氧,并指定時區(qū)
  
  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();
6.4 CronTrigger Misfire Instructions

下面的執(zhí)行可以告知==Quartz==當CronTrigger錯過執(zhí)行時該干點啥敏储,以下指令作為靜態(tài)常量存儲在==CronTrigger==中

CronTrigger 中的misfire指令靜態(tài)常量

MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY
MISFIRE_INSTRUCTION_DO_NOTHING
MISFIRE_INSTRUCTION_FIRE_NOW

所有的trigger 都擁有指令==Trigger.MISFIRE_INSTRUCTION_SMART_POLICY==,并且這個指令也是所有trigger的默認misfire類型朋鞍,不過在==CronTrigger==中被替換為==MISFIRE_INSTRUCTION_FIRE_NOW==

創(chuàng)建一個==CronTrigger==并指定 simple schedule 中的misfire 指令

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

7. TriggerListeners and JobListeners

trigger 事件監(jiān)聽 job 事件監(jiān)聽已添,==TriggerListeners==trigger的監(jiān)聽事件妥箕,==JobListeners==job的監(jiān)聽事件;

7.1 TriggerListener 接口

包括 trigger fire 和 trigger misfire


public interface TriggerListener {

    public String getName();

    public void triggerFired(Trigger trigger, JobExecutionContext context);

    public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context);

    public void triggerMisfired(Trigger trigger);

    public void triggerComplete(Trigger trigger, JobExecutionContext context,
            int triggerInstructionCode);
}

7.2 JobListener 接口

job 相關(guān)的事件主要包括job即將被執(zhí)行和job已經(jīng)執(zhí)行完畢

public interface JobListener {

    public String getName();

    public void jobToBeExecuted(JobExecutionContext context);

    public void jobExecutionVetoed(JobExecutionContext context);

    public void jobWasExecuted(JobExecutionContext context,
            JobExecutionException jobException);

}

7.3 配置自己的監(jiān)聽器

只要實現(xiàn)==org.quartz.TriggerListener== 或者 ==org.quartz.JobListener interface==更舞,便實現(xiàn)了自己的監(jiān)聽器畦幢,然后把監(jiān)聽器注冊到==scheduler==就可以使用了,前提你要給你的監(jiān)聽器起個名字

除了簡單實現(xiàn)上面這兩個接口外缆蝉,你也可以實現(xiàn)==JobListenerSupport==或==TriggerListenerSupport==來實現(xiàn)對自己感興趣的trigger 和 job 進行監(jiān)聽

使用==Matcher==就可以指定希望哪些==Jobs/Triggers==接收到事件

7.3.1 執(zhí)行job添加jobListener
scheduler.getListenerManager().addJobListener(myJobListener, KeyMatcher.jobKeyEquals(new JobKey("myJobName", "myJobGroup")));

需要導入的類

import static org.quartz.JobKey.*;
import static org.quartz.impl.matchers.KeyMatcher.*;
import static org.quartz.impl.matchers.GroupMatcher.*;
import static org.quartz.impl.matchers.AndMatcher.*;
import static org.quartz.impl.matchers.OrMatcher.*;
import static org.quartz.impl.matchers.EverythingMatcher.*;
...etc.
7.3.2 上面的例子也可以這樣寫
scheduler.getListenerManager().addJobListener(myJobListener, jobKeyEquals(jobKey("myJobName", "myJobGroup")));
7.3.3 給指定組下的所有job添加listener
scheduler.getListenerManager().addJobListener(myJobListener, jobGroupEquals("myJobGroup"));
7.3.4 給指定兩組的job添加listener
scheduler.getListenerManager().addJobListener(myJobListener, or(jobGroupEquals("myJobGroup"), jobGroupEquals("yourGroup")));
7.3.5 給所有的job添加listener
scheduler.getListenerManager().addJobListener(myJobListener, allJobs());

8. SchedulerListeners

除了Scheduler本身的一些通知事件外呛讲,==SchedulerListeners== 和 ==TriggerListeners==,==JobListeners==的功能很相似

事件主要包括job/trigger的添加返奉,移除贝搁,==scheduler==的一些異常通知,==scheduler==的==shutdown==通知等芽偏;

8.1 SchedulerListener
public interface SchedulerListener {

    public void jobScheduled(Trigger trigger);

    public void jobUnscheduled(String triggerName, String triggerGroup);

    public void triggerFinalized(Trigger trigger);

    public void triggersPaused(String triggerName, String triggerGroup);

    public void triggersResumed(String triggerName, String triggerGroup);

    public void jobsPaused(String jobName, String jobGroup);

    public void jobsResumed(String jobName, String jobGroup);

    public void schedulerError(String msg, SchedulerException cause);

    public void schedulerStarted();

    public void schedulerInStandbyMode();

    public void schedulerShutdown();

    public void schedulingDataCleared();
}

==SchedulerListeners== 使用 ==scheduler’s ListenerManager==注冊監(jiān)聽器

添加

scheduler.getListenerManager().addSchedulerListener(mySchedListener);

移除

scheduler.getListenerManager().removeSchedulerListener(mySchedListener);

9. Job Stores

jobstore 用來存儲scheduler下的job雷逆、trigger、calender等==work data==污尉,選擇合適的store方式非常重要

9.1 內(nèi)存存儲

任務(wù)信息存儲在內(nèi)容中膀哲,scheduler 被關(guān)閉或機器故障后,數(shù)據(jù)就丟了

org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
9.2 JDBCJobStore

支持的數(shù)據(jù)庫有==Oracle, PostgreSQL, MySQL, MS SQLServer, HSQLDB, and DB2==被碗,需要創(chuàng)建quartz單獨的數(shù)據(jù)庫表某宪,表結(jié)構(gòu)語句在==“docs/dbTables”==下,默認的事務(wù)類型==JobStoreTX==(最常見的)锐朴,如果你需要quartz和你的應(yīng)用服務(wù)使用同一個事務(wù)呵晚,需要使用事務(wù)類型為==JobStoreCMT==,這樣的化漓雅,quartz會讓應(yīng)用服務(wù)來管理quartz事務(wù)胆筒;

9.2.1 配置quartz 使用JobStoreTx
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
9.2.2 配置數(shù)據(jù)庫委托

數(shù)據(jù)庫委托信息在包==org.quartz.impl.jdbcjobstore==下

org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
9.2.3 quartz數(shù)據(jù)庫表的前綴
org.quartz.jobStore.tablePrefix = QRTZ_
9.2.4 配置數(shù)據(jù)源
org.quartz.jobStore.dataSource = myDS

可以指定==org.quartz.jobStore.useProperties==為==true==,這樣的就是以==String==類型存儲==JobDataMaps==信息酱酬,而不是==BLOB==

9.3 TerracottaJobStore

TerracottaJobStore可以是集群壶谒,也可以是單點的,不過都可以為作業(yè)數(shù)據(jù)提供存儲介質(zhì)膳沽,因為數(shù)據(jù)存儲在Terracotta服務(wù)器中汗菜,因此在應(yīng)用程序重新啟動期間是持久存儲的,挑社。它的性能比JDBCJobStore使用數(shù)據(jù)庫要好得多(大約好一個數(shù)量級)陨界,但是比RAMJobStore慢得多。

9.3.1 配置使用TerracottaJobStore
org.quartz.jobStore.class = org.terracotta.quartz.TerracottaJobStore
org.quartz.jobStore.tcConfigUrl = localhost:9510

10. Configuration, Resource Usage and SchedulerFactory

在使用quartz之前需要配置如下東西:

  • [x] 線程池 ThreadPool
  • [x] 任務(wù)存儲方式 JobStore
  • [x] 數(shù)據(jù)庫(如果必要的化)DataSources
  • [x] 調(diào)度器 Scheduler

ThreadPool

指定了任務(wù)同時執(zhí)行的并發(fā)數(shù)量滔灶,通常來說5個就夠了普碎,官方建議

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市录平,隨后出現(xiàn)的幾起案子麻车,更是在濱河造成了極大的恐慌缀皱,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件动猬,死亡現(xiàn)場離奇詭異啤斗,居然都是意外死亡,警方通過查閱死者的電腦和手機赁咙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門钮莲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人彼水,你說我怎么就攤上這事崔拥。” “怎么了凤覆?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵链瓦,是天一觀的道長。 經(jīng)常有香客問我盯桦,道長慈俯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任拥峦,我火速辦了婚禮贴膘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘略号。我一直安慰自己刑峡,他們只是感情好,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布璃哟。 她就那樣靜靜地躺著氛琢,像睡著了一般喊递。 火紅的嫁衣襯著肌膚如雪随闪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天骚勘,我揣著相機與錄音铐伴,去河邊找鬼。 笑死俏讹,一個胖子當著我的面吹牛当宴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播泽疆,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼户矢,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了殉疼?” 一聲冷哼從身側(cè)響起梯浪,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤捌年,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后挂洛,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體礼预,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年虏劲,在試婚紗的時候發(fā)現(xiàn)自己被綠了托酸。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡柒巫,死狀恐怖励堡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情堡掏,我是刑警寧澤念秧,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站布疼,受9級特大地震影響摊趾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜游两,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一砾层、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧贱案,春花似錦肛炮、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至瘩燥,卻和暖如春秕重,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背厉膀。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工溶耘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人服鹅。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓凳兵,卻偏偏與公主長得像,于是被迫代替她去往敵國和親企软。 傳聞我的和親對象是個殘疾皇子庐扫,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容