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


org.quartz包

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

其中接口有:

Calendar接口:

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

因而,可以把Calendar看做是排除了block時間的時間(例如:一個每5分鍾觸發一次的調度在周末(sunday)不執行,使用SimpleTrigger和WeeklyCalendar去排除周末這一天)。

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

 

 

Trigger接口:

 

 

 

 

 

 

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

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

若你使用Month作為時間間隔單位,請務必在設置開始時間時注意那天是否接近月底。例,如:你選擇1月31作為啟動時間,trigger 將設置觸發間隔為月份,下次觸發時間為2.28,下下次為3月28,接下來的觸發時間定位每月的28號,而不管那個月是否有31天。如果你需要一個在每月最后一天觸發的trigger(不管每月有多少天),請使用CronTrigger.

 

CronTrigger:使用CronExpression表達式作為觸發條件的Trigger的公開接口。

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

例一:每天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);

 

 

 


免責聲明!

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



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