quartz源碼分析之深入理解job,sheduler,calendar,trigger及listener之間的關係

org.quartz包

包org.quartz是Quartz的主包,包含了客戶端接口。html

其中接口有:java

Calendar接口:

定義了一個關聯Trigger可能(或者不可能)觸發的時間空間。它沒有定義觸發的真實時間,而是用在在普通的Schedule須要限制Trigger觸發的時候。大部分Calendar包含默認全部的時間,而且用戶去排除部分時間。shell

於是,能夠把Calendar看作是排除了block時間的時間(例如:一個每5分鐘觸發一次的調度在週末(sunday)不執行,使用SimpleTrigger和WeeklyCalendar去排除週末這一天)。安全

注意:Calendar實現了序列化和可克隆接口。ui

 

 

Trigger接口:

 

 

 

 

 

 

CalendarIntervalTrigger是一個具體的Trigger,用來觸發基於定時重複的JobDetail。this

Trigger將會每隔N個calendar在trigger中定義的時間單元觸發一次。這個trigger不適合使用SimpleTrigger完成(例如因爲每個月的時間不是固定的描述),也不適用於CronTrigger(例如每5個月)。線程

若你使用Month做爲時間間隔單位,請務必在設置開始時間時注意那天是否接近月底。例,如:你選擇1月31做爲啓動時間,trigger 將設置觸發間隔爲月份,下次觸發時間爲2.28,下下次爲3月28,接下來的觸發時間定位每個月的28號,而無論那個月是否有31天。若是你須要一個在每個月最後一天觸發的trigger(無論每個月有多少天),請使用CronTrigger.代理

 

CronTrigger:使用CronExpression表達式做爲觸發條件的Trigger的公開接口。code

DailyTimeIntervalTrigger用來觸發一個基於天天定時間隔執行的JobDetail。Trigger在跟定的時間內每隔N(個體RepeatInterval())秒、分、小時(getRepeatIntervalUnit())觸發一次。htm

例一:天天8:00~11:00之間每72分鐘執行一次,它的觸發事件爲8:00,9:12,10:24,而後明天繼續:8:00,9:12,10:24。

例二:從週一到週五的天天9:20~16:47 每隔23分鐘執行一次。

天天,開始時間被重置爲startTimeOfDay,直至一天endTimeOfDay到以前,都將重複的間隔時間向上加。

TriggerListener接口

 

 

Job接口:

Job:job表明了要容許的任務即業務邏輯。它必須具備一個公開的無參構造方法。JobDataMap提供了Job實例參數數據的機制,它會在一些實現給接口的類中須要這一機制。有惟一的方法:execute(JobExecutionContext context):當一個關聯到這個job的Trigger須要觸發時由Scheduler來調用該方法。

 

JobDetail:保存一個job實例的詳細屬性。它在JobBuilder中建立/定義。

JobDetailImpl:存一個job實例的詳細屬性,Quartz不保存一個Job類的真實實例,相反,容許你經過使用JobDetail定義一個job實例。Job 有名稱和所屬的組別,scheduler能夠經過組別和名稱來找到惟一的一個job。Trigger 是job被調度的機制,許多Trigger能夠指向同一個Job,但一個Trigger僅僅能執行一個Job

    private String name;

 

    private String group = Scheduler.DEFAULT_GROUP;

 

    private String description;

 

    private Class<? extends Job> jobClass;

 

    private JobDataMap jobDataMap;

 

    private boolean durability = false;

 

    private boolean shouldRecover = false;

 

    private transient JobKey key = null;

其中,JobKey定義了job的名稱和組別。

JobBuilder:用來初始化JobDetail實例。

 

 

 

 

 

JobListener

實現了該接口的類會監聽JobDetail執行的方法。一般,使用Scheduler的應用將不會應用這一機制。

ListenerManager:JobListener提供了對Job執行的監聽;TriggerListener提供對trigger觸發的監聽;SchedulerListener提供了Scheduler事件和錯誤的監聽。經過ListenerManager接口將Listener和本地scheduler關聯到一塊兒。ListenerManagerImpl是實現類。

 

Listener的註冊順序是保持的,所以Listener的監聽順序和他們註冊的順序一致。

 

JobFactory接口:

public class PropertySettingJobFactory extends SimpleJobFactory {}

public class SimpleJobFactory implements JobFactory {}

 

TriggerFiredBundle:JobStore返回給QuartzSchedulerThread的執行時期數據。

   private JobDetail job;

 

    private OperableTrigger trigger;

 

    private Calendar cal;

 

    private boolean jobIsRecovering;

 

    private Date fireTime;

 

    private Date scheduledFireTime;

 

    private Date prevFireTime;

 

    private Date nextFireTime;

Scheduler接口:

一個scheduler維護一個JobDetail和一個或者多個Trigger的註冊。一旦註冊,scheduler負責在job關聯的Trigger觸發時(當調度到達時間)執行該job。

Scheduler實例有SchedulerFactory建立產生。一個已經建立或者初始化的scheduler能夠被建立它的工廠查詢和使用。在一個scheduler被建立後,它處於」STAND-BY」模式,在觸發任何job前須要使用它的start()方法來啓動。

客戶端程序經過定義一個實現了job接口的類來建立Job,JobDetail對象同時對建立(客戶端)來定義一個單獨的job實例。JobDetail實例而後經過ScheduleJob(JobDetail,Trigger)或者addJob(JobDetail,boolean)方法註冊到Scheduler。

Trigger定義用來觸發基於給定Scheduler的單獨的job實例,SimpleTrigger對觸發一次或精確時間的觸發、在給定延遲後重復觸發的應用中很是有用。Contrigger容許基於一天中的具體時間、一週中的一天、一月中的一天、一年中的一個月的調度。

Job和trigger都具備名稱和關聯的組別,這是它們在一個單獨Scheduler的惟一身份識別碼。組別的這個特徵在建立邏輯組或對job和Trigger進行歸類時很是有用。若是你不想對給定的job和trigger指定一個分組,可使用默認組常量,這個常量已經在接口中定義好了。

 

存儲的Job也能夠手動觸發,經過使用trigger(String JobName,String jobGroup)這個方法能夠實現手動觸發job。

 

客戶端程序可能會對Quartz中的Listener接口感興趣,JobListener提供了對job執行的監聽;TriggerListner提供了對Trigger觸發的監聽;SchedulerListener提供了對事件調度和錯誤的監聽。經過使用ListenerManager接口將Listener和本地的Scheduler關聯起來。Scheduler的建立和配置均可以自定義。請參考發佈的Quartz的文檔。

 

 

SchedulerListener接口:

<略>

 

org.quartz.core包

JobRunShell

jobRunShell實例負責爲job運行提供安全的環境、運行job所需工做、捕獲排除的任何異常、更新執行完成job代碼的Trigger等。

jobRunShell實例由JobRunShellFactory建立,當sheduler決定觸發一個job時,QuartzSchedulerThread從配置的線程池中返回一個shell。看一下jobRunShel的調用關係:

  1. QuartzScheduler構造方法初始化線程池:

/**

     * <p>

     * Create a <code>QuartzScheduler</code> with the given configuration

     * properties.

     * </p>

     *

     * @see QuartzSchedulerResources

     */

    public QuartzScheduler(QuartzSchedulerResources resources, long idleWaitTime, @Deprecated long dbRetryInterval)

        throws SchedulerException {

        this.resources = resources;

        if (resources.getJobStore() instanceof JobListener) {

            addInternalJobListener((JobListener)resources.getJobStore());

        }

 

        this.schedThread = new QuartzSchedulerThread(this, resources);

        ThreadExecutor schedThreadExecutor = resources.getThreadExecutor();

        schedThreadExecutor.execute(this.schedThread);

        if (idleWaitTime > 0) {

            this.schedThread.setIdleWaitTime(idleWaitTime);

        }

 

        jobMgr = new ExecutingJobsManager();

        addInternalJobListener(jobMgr);

        errLogger = new ErrorLogger();

        addInternalSchedulerListener(errLogger);

 

        signaler = new SchedulerSignalerImpl(this, this.schedThread);

       

        if(shouldRunUpdateCheck())

            updateTimer = scheduleUpdateCheck();

        else

            updateTimer = null;

       

        getLog().info("Quartz Scheduler v." + getVersion() + " created.");

    }

 

 

QuartzSchedulerThread啓動時調用JobRunShell

JobRunShell shell = null;

try{

   shell = qsRsrcs.getJobRunShellFactory().createJobRunShell(bndle);

   shell.initialize(qs);

   }

 

 

 

 

 

QuartzScheduler

這個類是Quartz的核心,間接繼承了Scheduler接口,包含了調度Job、註冊JobListener實例的方法。

QuartzSchedulerResources:包含了JobStore、線程池等建立一個QuartzScheduler實例所必需要的全部資源。

 

 

SchedulerContext:保存job運行時須要的上下文/環境數據,這個特徵和J2EE中servlet的ServletContext特徵特別相像。

之後的Quartz版本將會在代理實例和單獨的scheduler實例如何在SchedulerContext擴展數據作出區分。

 

SchedulerSignaler:JobStore實例使用的接口,用來傳回信號到QuartzScheduler。

    void notifyTriggerListenersMisfired(Trigger trigger);

 

    void notifySchedulerListenersFinalized(Trigger trigger);

 

    void notifySchedulerListenersJobDeleted(JobKey jobKey);

 

    void signalSchedulingChange(long candidateNewNextFireTime);

 

void notifySchedulerListenersError(String string, SchedulerException jpe);

相關文章
相關標籤/搜索