參考資料
第一篇配合第二篇閱讀,講解一些基本概念。若已瞭解可跳過。
推薦閱讀第三篇,因爲本文是基於第三篇的筆記。
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裏了。