Quartz源碼節選(三)添加Job和Trigger到Scheduler中

參考資料

第一篇配合第二篇閱讀,講解一些基本概念。若已瞭解可跳過。
推薦閱讀第三篇,因爲本文是基於第三篇的筆記。

DEMO

一個DEMO,每3秒輸出helloworld

public class MyJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        JobDataMap jobDataMap = context.getMergedJobDataMap();
        String say = jobDataMap.getString("say");
        System.out.println(say);
    }
}
public class Demo {
    public static void main(String[] args) {
        JobDetail jd = JobBuilder.newJob(MyJob.class)
                .withIdentity("myJob","jobGroup1")
                .withDescription("a demo jobDetail")
                .usingJobData("say","helloworld")
                .build();

        CronTrigger cronTrigger = TriggerBuilder.newTrigger()
                .withIdentity("myCronTrigger","triggerGroup1")
                .withSchedule(CronScheduleBuilder.cronSchedule("0/3 * * * * ?"))
                .forJob(jd)
                .build();
        
        try {
            Scheduler scheduler = new StdSchedulerFactory().getScheduler(); 
            scheduler.scheduleJob(jd,cronTrigger);//本文要講的部分
            scheduler.start();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }
}

StdScheduler和QuartzScheduler的關係

StdScheduler大部分方法都委託內部的QuartzScheduler實現,除了getMetaData()方法

public class StdScheduler implements Scheduler {
    private QuartzScheduler sched;
    /*
     *省略部分代碼
     */
    public Date scheduleJob(JobDetail jobDetail, Trigger trigger)
        throws SchedulerException {
        return sched.scheduleJob(jobDetail, trigger);//實際由QuartzScheduler執行
    }
    /*
     *省略部分代碼
     */
    public SchedulerMetaData getMetaData() {
        return new SchedulerMetaData(getSchedulerName(),
                getSchedulerInstanceId(), getClass(), false, isStarted(), 
                isInStandbyMode(), isShutdown(), sched.runningSince(), 
                sched.numJobsExecuted(), sched.getJobStoreClass(), 
                sched.supportsPersistence(), sched.isClustered(), sched.getThreadPoolClass(), 
                sched.getThreadPoolSize(), sched.getVersion());

    }
}

JobDetail和Trigger加入到調度中

既然是委託的,那可以直接看QuartzScheduler.scheduleJob(JobDetail jobDetail, Trigger trigger)

  • QuartzScheduler.scheduleJob(JobDetail jobDetail, Trigger trigger)
public Date scheduleJob(JobDetail jobDetail, Trigger trigger) throws SchedulerException {
    validateState();

    if (jobDetail == null) {
        throw new SchedulerException("JobDetail cannot be null");
    }

    if (trigger == null) {
        throw new SchedulerException("Trigger cannot be null");
    }

    if (jobDetail.getKey() == null) {
        throw new SchedulerException("Job's key cannot be null");
    }

    if (jobDetail.getJobClass() == null) {
        throw new SchedulerException("Job's class cannot be null");
    }

    OperableTrigger trig = (OperableTrigger)trigger;

    //這裏的操作和TriggerBuilder.forJob()類似
    if (trigger.getJobKey() == null) { 
        trig.setJobKey(jobDetail.getKey());
    } else if (!trigger.getJobKey().equals(jobDetail.getKey())) {
        throw new SchedulerException(
            "Trigger does not reference given job!");
    }

    trig.validate();

    Calendar cal = null;
    if (trigger.getCalendarName() != null) {
        cal = resources.getJobStore().retrieveCalendar(trigger.getCalendarName());
    }
    Date ft = trig.computeFirstFireTime(cal);

    if (ft == null) {
        throw new SchedulerException(
            "Based on configured schedule, the given trigger '" + trigger.getKey() + "' will never fire.");
    }
    
    resources.getJobStore().storeJobAndTrigger(jobDetail, trig);//JobStore保存JobDetail和Trigger信息
    notifySchedulerListenersJobAdded(jobDetail);
    notifySchedulerThread(trigger.getNextFireTime().getTime());
    notifySchedulerListenersSchduled(trigger);

    return ft;
}

JobStore保存JobDetail和Trigger的信息

JobStore的一個基本功能是保存JobDetail和Trigger的信息。JobStroe多種實現。比如JobStoreSupport能將數據保存到數據庫中,涉及一些數據庫連接的操作,RAMJobStore將信息保存在內存中。

public class RAMJobStore implements JobStore {

    //按key分類
    protected HashMap<JobKey, JobWrapper> jobsByKey = new HashMap<JobKey, JobWrapper>(1000);
    protected HashMap<TriggerKey, TriggerWrapper> triggersByKey = new HashMap<TriggerKey, TriggerWrapper>(1000);
	//按group分類
    protected HashMap<String, HashMap<JobKey, JobWrapper>> jobsByGroup = new HashMap<String, HashMap<JobKey, JobWrapper>>(25);
    protected HashMap<String, HashMap<TriggerKey, TriggerWrapper>> triggersByGroup = new HashMap<String, HashMap<TriggerKey, TriggerWrapper>>(25);
	//TreeSet保證trigger不重複並能按照最優先的處理去排序
    protected TreeSet<TriggerWrapper> timeTriggers = new TreeSet<TriggerWrapper>(new TriggerWrapperComparator());

    protected HashMap<String, Calendar> calendarsByName = new HashMap<String, Calendar>(25);

    protected Map<JobKey, List<TriggerWrapper>> triggersByJob = new HashMap<JobKey, List<TriggerWrapper>>(1000);

    protected final Object lock = new Object();

    protected HashSet<String> pausedTriggerGroups = new HashSet<String>();
    protected HashSet<String> pausedJobGroups = new HashSet<String>();
    protected HashSet<JobKey> blockedJobs = new HashSet<JobKey>();
    
    protected long misfireThreshold = 5000l;
    protected SchedulerSignaler signaler;
    private final Logger log = LoggerFactory.getLogger(getClass());
  • RAMJobStore.storeJobAndTrigger(JobDetail newJob, OperableTrigger newTrigger)
public void storeJobAndTrigger(JobDetail newJob, OperableTrigger newTrigger) throws JobPersistenceException {
    storeJob(newJob, false);
    storeTrigger(newTrigger, false);
}

  • RAMJobStore.storeJob(JobDetail newJob, boolean replaceExisting)
public void storeJob(JobDetail newJob,
            boolean replaceExisting) throws ObjectAlreadyExistsException {
        JobWrapper jw = new JobWrapper((JobDetail)newJob.clone());

        boolean repl = false;

        synchronized (lock) {
            if (jobsByKey.get(jw.key) != null) {
                if (!replaceExisting) {
                    throw new ObjectAlreadyExistsException(newJob);
                }
                repl = true;
            }

            if (!repl) {
                // get job group
                HashMap<JobKey, JobWrapper> grpMap = jobsByGroup.get(newJob.getKey().getGroup());
                if (grpMap == null) {
                    grpMap = new HashMap<JobKey, JobWrapper>(100);
                    jobsByGroup.put(newJob.getKey().getGroup(), grpMap);
                }
                // add to jobs by group
                grpMap.put(newJob.getKey(), jw);
                // add to jobs by FQN map
                jobsByKey.put(jw.key, jw);
            } else {
                // update job detail
                JobWrapper orig = jobsByKey.get(jw.key);
                orig.jobDetail = jw.jobDetail; // already cloned
            }
        }
    }

storeJob(newJob, false)和storeTrigger(newTrigger, false)n內容差不多,都是按key和按group保存Job或者Trigger信息

現在,JobDetail和Trigger已經添加到Scheduler裏了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章