quartz官方提供了15个example,方便开发者理解quartz的用法。现在结合源码对实例的使用进行分析。
参见:
http://www.quartz-scheduler.org/documentation/quartz-2.2.x/examples/
example1:First Quartz Program
1、实例内容包括:
-
启动Quartz Scheduler
-
等待下一个整点后执行任务
-
退出Quartz Scheduler
2、代码:
-
SimpleExample:主体程序
-
HelloJob:一个简单的任务,打印Hello World
HelloJob:
-
public class HelloJob implements Job {
-
-
private static Logger _log = LoggerFactory.getLogger(HelloJob.class);
-
-
-
public HelloJob() {
-
}
-
-
-
public void execute(JobExecutionContext context)
-
throws JobExecutionException {
-
-
// Say Hello to the World and display the date/time
-
_log.info("Hello World! - " + new Date());
-
}
-
-
}
查上面代码,HelloJob只是一个很简单的定时任务,实现了Job接口,同时实现了execute方法,然后方法内打印了当前时间。
SimpleExample:
-
-
-
package org.quartz.examples.example1;
-
-
import static org.quartz.DateBuilder.evenMinuteDate;
-
import static org.quartz.JobBuilder.newJob;
-
import static org.quartz.TriggerBuilder.newTrigger;
-
-
import org.quartz.JobDetail;
-
import org.quartz.Scheduler;
-
import org.quartz.SchedulerFactory;
-
import org.quartz.Trigger;
-
import org.quartz.impl.StdSchedulerFactory;
-
import org.slf4j.Logger;
-
import org.slf4j.LoggerFactory;
-
-
import java.util.Date;
-
-
/**
-
* This Example will demonstrate how to start and shutdown the Quartz scheduler and how to schedule a job to run in
-
* Quartz.
-
*
-
* @author Bill Kratzer
-
*/
-
public class SimpleExample {
-
-
public void run() throws Exception {
-
Logger log = LoggerFactory.getLogger(SimpleExample.class);
-
-
log.info("------- Initializing ----------------------");
-
-
// First we must get a reference to a scheduler
-
SchedulerFactory sf = new StdSchedulerFactory();
-
Scheduler sched = sf.getScheduler();
-
-
log.info("------- Initialization Complete -----------");
-
-
// computer a time that is on the next round minute
-
Date runTime = evenMinuteDate(new Date());
-
-
log.info("------- Scheduling Job -------------------");
-
-
// define the job and tie it to our HelloJob class
-
JobDetail job = newJob(HelloJob.class).withIdentity("job1", "group1").build();
-
-
// Trigger the job to run on the next round minute
-
Trigger trigger = newTrigger().withIdentity("trigger1", "group1").startAt(runTime).build();
-
-
// Tell quartz to schedule the job using our trigger
-
sched.scheduleJob(job, trigger);
-
log.info(job.getKey() + " will run at: " + runTime);
-
-
// Start up the scheduler (nothing can actually run until the
-
// scheduler has been started)
-
sched.start();
-
-
log.info("------- Started Scheduler -----------------");
-
-
// wait long enough so that the scheduler as an opportunity to
-
// run the job!
-
log.info("------- Waiting 65 seconds... -------------");
-
try {
-
// wait 65 seconds to show job
-
Thread.sleep(65L * 1000L);
-
// executing...
-
} catch (Exception e) {
-
//
-
}
-
-
// shut down the scheduler
-
log.info("------- Shutting Down ---------------------");
-
sched.shutdown(true);
-
log.info("------- Shutdown Complete -----------------");
-
}
-
-
public static void main(String[] args) throws Exception {
-
-
SimpleExample example = new SimpleExample();
-
example.run();
-
-
}
-
-
}
1)首先创建一个Scheduler,参照quartz详解2,此时还没有打开启动quartz的主线程QuartzSchedulerThread的开关。
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sched = sf.getScheduler();
2)定义JobDetail和Trigger,并添加一个定时任务,在下一个整点执行:
Date runTime = evenMinuteDate(new Date());
// define the job and tie it to our HelloJob class
Date runTime = evenMinuteDate(new Date());JobDetail job = newJob(HelloJob.class).withIdentity("job1", "group1").build();
Trigger trigger = newTrigger().withIdentity("trigger1", "group1").startAt(runTime).build();
sched.scheduleJob(job, trigger);
3)打开开关启动scheduler
// define the job and tie it to our HelloJob class
sched.start();
4)等待65秒后停止Scheduler
sched.shutdown(true);
Example 2 - Simple Triggers
1、实例内容也是Simple Trigger的使用,不一样的是批量的使用。
2、代码:
-
SimpleTriggerExample:主体程序
-
SimpleJob:一个简单的任务,打印当前时间
SimpleJob:
-
public void execute(JobExecutionContext context)
-
throws JobExecutionException {
-
-
// This job simply prints out its job name and the
-
// date and time that it is running
-
JobKey jobKey = context.getJobDetail().getKey();
-
_log.info("SimpleJob says: " + jobKey + " executing at " + new Date());
-
}
SimpleTriggerExample:
-
/*
-
* All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved.
-
*
-
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
-
* use this file except in compliance with the License. You may obtain a copy
-
* of the License at
-
*
-
* http://www.apache.org/licenses/LICENSE-2.0
-
*
-
* Unless required by applicable law or agreed to in writing, software
-
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-
* License for the specific language governing permissions and limitations
-
* under the License.
-
*
-
*/
-
-
package org.quartz.examples.example2;
-
-
import static org.quartz.DateBuilder.futureDate;
-
import static org.quartz.JobBuilder.newJob;
-
import static org.quartz.JobKey.jobKey;
-
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
-
import static org.quartz.TriggerBuilder.newTrigger;
-
-
import org.quartz.DateBuilder;
-
import org.quartz.DateBuilder.IntervalUnit;
-
import org.quartz.JobDetail;
-
import org.quartz.Scheduler;
-
import org.quartz.SchedulerFactory;
-
import org.quartz.SchedulerMetaData;
-
import org.quartz.SimpleTrigger;
-
import org.quartz.impl.StdSchedulerFactory;
-
import org.slf4j.Logger;
-
import org.slf4j.LoggerFactory;
-
-
import java.util.Date;
-
-
/**
-
* This Example will demonstrate all of the basics of scheduling capabilities of Quartz using Simple Triggers.
-
*
-
* @author Bill Kratzer
-
*/
-
public class SimpleTriggerExample {
-
-
public void run() throws Exception {
-
Logger log = LoggerFactory.getLogger(SimpleTriggerExample.class);
-
-
log.info("------- Initializing -------------------");
-
-
// First we must get a reference to a scheduler
-
SchedulerFactory sf = new StdSchedulerFactory();
-
Scheduler sched = sf.getScheduler();
-
-
log.info("------- Initialization Complete --------");
-
-
log.info("------- Scheduling Jobs ----------------");
-
-
// jobs can be scheduled before sched.start() has been called
-
-
// get a "nice round" time a few seconds in the future...
-
Date startTime = DateBuilder.nextGivenSecondDate(null, 15);
-
-
// job1 will only fire once at date/time "ts"
-
JobDetail job = newJob(SimpleJob.class).withIdentity("job1", "group1").build();
-
-
SimpleTrigger trigger = (SimpleTrigger) newTrigger().withIdentity("trigger1", "group1").startAt(startTime).build();
-
-
// schedule it to run!
-
Date ft = sched.scheduleJob(job, trigger);
-
log.info(job.getKey() + " will run at: " + ft + " and repeat: " + trigger.getRepeatCount() + " times, every "
-
+ trigger.getRepeatInterval() / 1000 + " seconds");
-
-
// job2 will only fire once at date/time "ts"
-
job = newJob(SimpleJob.class).withIdentity("job2", "group1").build();
-
-
trigger = (SimpleTrigger) newTrigger().withIdentity("trigger2", "group1").startAt(startTime).build();
-
-
ft = sched.scheduleJob(job, trigger);
-
log.info(job.getKey() + " will run at: " + ft + " and repeat: " + trigger.getRepeatCount() + " times, every "
-
+ trigger.getRepeatInterval() / 1000 + " seconds");
-
-
// job3 will run 11 times (run once and repeat 10 more times)
-
// job3 will repeat every 10 seconds
-
job = newJob(SimpleJob.class).withIdentity("job3", "group1").build();
-
-
trigger = newTrigger().withIdentity("trigger3", "group1").startAt(startTime)
-
.withSchedule(simpleSchedule().withIntervalInSeconds(10).withRepeatCount(10)).build();
-
-
ft = sched.scheduleJob(job, trigger);
-
log.info(job.getKey() + " will run at: " + ft + " and repeat: " + trigger.getRepeatCount() + " times, every "
-
+ trigger.getRepeatInterval() / 1000 + " seconds");
-
-
// the same job (job3) will be scheduled by a another trigger
-
// this time will only repeat twice at a 70 second interval
-
-
trigger = newTrigger().withIdentity("trigger3", "group2").startAt(startTime)
-
.withSchedule(simpleSchedule().withIntervalInSeconds(10).withRepeatCount(2)).forJob(job).build();
-
-
ft = sched.scheduleJob(trigger);
-
log.info(job.getKey() + " will [also] run at: " + ft + " and repeat: " + trigger.getRepeatCount()
-
+ " times, every " + trigger.getRepeatInterval() / 1000 + " seconds");
-
-
// job4 will run 6 times (run once and repeat 5 more times)
-
// job4 will repeat every 10 seconds
-
job = newJob(SimpleJob.class).withIdentity("job4", "group1").build();
-
-
trigger = newTrigger().withIdentity("trigger4", "group1").startAt(startTime)
-
.withSchedule(simpleSchedule().withIntervalInSeconds(10).withRepeatCount(5)).build();
-
-
ft = sched.scheduleJob(job, trigger);
-
log.info(job.getKey() + " will run at: " + ft + " and repeat: " + trigger.getRepeatCount() + " times, every "
-
+ trigger.getRepeatInterval() / 1000 + " seconds");
-
-
// job5 will run once, five minutes in the future
-
job = newJob(SimpleJob.class).withIdentity("job5", "group1").build();
-
-
trigger = (SimpleTrigger) newTrigger().withIdentity("trigger5", "group1")
-
.startAt(futureDate(5, IntervalUnit.MINUTE)).build();
-
-
ft = sched.scheduleJob(job, trigger);
-
log.info(job.getKey() + " will run at: " + ft + " and repeat: " + trigger.getRepeatCount() + " times, every "
-
+ trigger.getRepeatInterval() / 1000 + " seconds");
-
-
// job6 will run indefinitely, every 40 seconds
-
job = newJob(SimpleJob.class).withIdentity("job6", "group1").build();
-
-
trigger = newTrigger().withIdentity("trigger6", "group1").startAt(startTime)
-
.withSchedule(simpleSchedule().withIntervalInSeconds(40).repeatForever()).build();
-
-
ft = sched.scheduleJob(job, trigger);
-
log.info(job.getKey() + " will run at: " + ft + " and repeat: " + trigger.getRepeatCount() + " times, every "
-
+ trigger.getRepeatInterval() / 1000 + " seconds");
-
-
log.info("------- Starting Scheduler ----------------");
-
-
// All of the jobs have been added to the scheduler, but none of the jobs
-
// will run until the scheduler has been started
-
sched.start();
-
-
log.info("------- Started Scheduler -----------------");
-
-
// jobs can also be scheduled after start() has been called...
-
// job7 will repeat 20 times, repeat every five minutes
-
job = newJob(SimpleJob.class).withIdentity("job7", "group1").build();
-
-
trigger = newTrigger().withIdentity("trigger7", "group1").startAt(startTime)
-
.withSchedule(simpleSchedule().withIntervalInMinutes(5).withRepeatCount(20)).build();
-
-
ft = sched.scheduleJob(job, trigger);
-
log.info(job.getKey() + " will run at: " + ft + " and repeat: " + trigger.getRepeatCount() + " times, every "
-
+ trigger.getRepeatInterval() / 1000 + " seconds");
-
-
// jobs can be fired directly... (rather than waiting for a trigger)
-
job = newJob(SimpleJob.class).withIdentity("job8", "group1").storeDurably().build();
-
-
sched.addJob(job, true);
-
-
log.info("'Manually' triggering job8...");
-
sched.triggerJob(jobKey("job8", "group1"));
-
-
log.info("------- Waiting 30 seconds... --------------");
-
-
try {
-
// wait 33 seconds to show jobs
-
Thread.sleep(30L * 1000L);
-
// executing...
-
} catch (Exception e) {
-
//
-
}
-
-
// jobs can be re-scheduled...
-
// job 7 will run immediately and repeat 10 times for every second
-
log.info("------- Rescheduling... --------------------");
-
trigger = newTrigger().withIdentity("trigger7", "group1").startAt(startTime)
-
.withSchedule(simpleSchedule().withIntervalInMinutes(5).withRepeatCount(20)).build();
-
-
ft = sched.rescheduleJob(trigger.getKey(), trigger);
-
log.info("job7 rescheduled to run at: " + ft);
-
-
log.info("------- Waiting five minutes... ------------");
-
try {
-
// wait five minutes to show jobs
-
Thread.sleep(300L * 1000L);
-
// executing...
-
} catch (Exception e) {
-
//
-
}
-
-
log.info("------- Shutting Down ---------------------");
-
-
sched.shutdown(true);
-
-
log.info("------- Shutdown Complete -----------------");
-
-
// display some stats about the schedule that just ran
-
SchedulerMetaData metaData = sched.getMetaData();
-
log.info("Executed " + metaData.getNumberOfJobsExecuted() + " jobs.");
-
-
}
-
-
public static void main(String[] args) throws Exception {
-
-
SimpleTriggerExample example = new SimpleTriggerExample();
-
example.run();
-
-
}
-
-
}
job3每10秒执行1次,重复10次,一共执行11次。
-
// job3 will run 11 times (run once and repeat 10 more times)
-
// job3 will repeat every 10 seconds
-
job = newJob(SimpleJob.class).withIdentity("job3", "group1").build();
-
-
trigger = newTrigger().withIdentity("trigger3", "group1").startAt(startTime)
-
.withSchedule(simpleSchedule().withIntervalInSeconds(10).withRepeatCount(10)).build();
同样是job3,新增一个trigger来触发它。
因为在版本2.2.1中,是可以支持多个trigger来对应触发同一个JOB的。
-
trigger = newTrigger().withIdentity("trigger3", "group2").startAt(startTime)
-
.withSchedule(simpleSchedule().withIntervalInSeconds(10).withRepeatCount(2)).forJob(job).build();
job5也可以设置5分钟后执行:
-
// job5 will run once, five minutes in the future
-
job = newJob(SimpleJob.class).withIdentity("job5", "group1").build();
-
-
trigger = (SimpleTrigger) newTrigger().withIdentity("trigger5", "group1")
-
.startAt(futureDate(5, IntervalUnit.MINUTE)).build();
job6设置每40秒执行,一直执行:
-
job = newJob(SimpleJob.class).withIdentity("job6", "group1").build();
-
-
trigger = newTrigger().withIdentity("trigger6", "group1").startAt(startTime)
-
.withSchedule(simpleSchedule().withIntervalInSeconds(40).repeatForever()).build();
job7是可以在scheduler启动后再创建,加入到scheduler中。
job8表示,不需要创建trigger,可以直接触发任务。
example3:Cron Trigger
job1是每20秒执行一次:
-
JobDetail job = newJob(SimpleJob.class)
-
.withIdentity("job1", "group1")
-
.build();
-
-
CronTrigger trigger = newTrigger()
-
.withIdentity("trigger1", "group1")
-
.withSchedule(cronSchedule("0/20 * * * * ?"))
-
.build();
-
-
sched.scheduleJob(job, trigger);
Jo2是每2分钟执行一次,在15秒这个点执行。如1分15秒,3分15秒,5分15秒。
-
JobDetail job = newJob(SimpleJob.class)
-
.withIdentity("job1", "group1")
-
.build();
-
-
CronTrigger trigger = newTrigger()
-
.withIdentity("trigger1", "group1")
-
.withSchedule(cronSchedule("0/20 * * * * ?"))
-
.build();
-
-
sched.scheduleJob(job, trigger);
JOB3是每2分种的整点执行一次,在上午8点到下午17点之间。
-
// job 3 will run every other minute but only between 8am and 5pm
-
job = newJob(SimpleJob.class).withIdentity("job3", "group1").build();
-
-
trigger = newTrigger().withIdentity("trigger3", "group1").withSchedule(cronSchedule("0 0/2 8-17 * * ?")).build();
-
-
ft = sched.scheduleJob(job, trigger);
-
log.info(job.getKey() + " has been scheduled to run at: " + ft + " and repeat based on expression: "
-
+ trigger.getCronExpression());
JOB5在每个月1号和15号的上午10点执行:
-
// job 5 will run at 10am on the 1st and 15th days of the month
-
job = newJob(SimpleJob.class).withIdentity("job5", "group1").build();
-
-
trigger = newTrigger().withIdentity("trigger5", "group1").withSchedule(cronSchedule("0 0 10am 1,15 * ?")).build();
-
-
ft = sched.scheduleJob(job, trigger);
-
log.info(job.getKey() + " has been scheduled to run at: " + ft + " and repeat based on expression: "
-
+ trigger.getCronExpression());
JOB6在每周一到周五执行,每30秒执行一次。
"0,30 * * ? * MON-FRI"
JOB7在每个周六和周日执行,每30秒执行一次。
"0,30 * * ? * MON-FRI"
Example 4 - Job Parameters and Job State
可以为job设置参数和状态。
@DisallowConcurrentExecution 注解的含义相关于1.8.6版本中的stateful job,就是说同一个trigger在上一次没有执行完成时,下一个不能执行。
比如trigger是30s执行一次,一个任务执行了37秒,那么第二个任务需要等37s后,前一个任务执行后了才可以执行。
那么第二个任务是在37s执行,还是在下一个周期60s的时候执行呢?
@PersistJobDataAfterExecution 代表执行完后的job的数据在jobMap中不共享,一般用于有状态的job...
-
@PersistJobDataAfterExecution
-
@DisallowConcurrentExecution
-
public class ColorJob implements Job {
看一下例子:
-
public class JobStateExample {
-
-
public void run() throws Exception {
-
Logger log = LoggerFactory.getLogger(JobStateExample.class);
-
-
log.info("------- Initializing -------------------");
-
-
// First we must get a reference to a scheduler
-
SchedulerFactory sf = new StdSchedulerFactory();
-
Scheduler sched = sf.getScheduler();
-
-
log.info("------- Initialization Complete --------");
-
-
log.info("------- Scheduling Jobs ----------------");
-
-
// get a "nice round" time a few seconds in the future....
-
Date startTime = nextGivenSecondDate(null, 10);
-
-
// job1 will only run 5 times (at start time, plus 4 repeats), every 10 seconds
-
JobDetail job1 = newJob(ColorJob.class).withIdentity("job1", "group1").build();
-
-
SimpleTrigger trigger1 = newTrigger().withIdentity("trigger1", "group1").startAt(startTime)
-
.withSchedule(simpleSchedule().withIntervalInSeconds(10).withRepeatCount(4)).build();
-
-
// pass initialization parameters into the job
-
job1.getJobDataMap().put(ColorJob.FAVORITE_COLOR, "Green");
-
job1.getJobDataMap().put(ColorJob.EXECUTION_COUNT, 1);
-
-
// schedule the job to run
-
Date scheduleTime1 = sched.scheduleJob(job1, trigger1);
-
log.info(job1.getKey() + " will run at: " + scheduleTime1 + " and repeat: " + trigger1.getRepeatCount()
-
+ " times, every " + trigger1.getRepeatInterval() / 1000 + " seconds");
-
-
// job2 will also run 5 times, every 10 seconds
-
JobDetail job2 = newJob(ColorJob.class).withIdentity("job2", "group1").build();
-
-
SimpleTrigger trigger2 = newTrigger().withIdentity("trigger2", "group1").startAt(startTime)
-
.withSchedule(simpleSchedule().withIntervalInSeconds(10).withRepeatCount(4)).build();
-
-
// pass initialization parameters into the job
-
// this job has a different favorite color!
-
job2.getJobDataMap().put(ColorJob.FAVORITE_COLOR, "Red");
-
job2.getJobDataMap().put(ColorJob.EXECUTION_COUNT, 1);
-
-
// schedule the job to run
-
Date scheduleTime2 = sched.scheduleJob(job2, trigger2);
-
log.info(job2.getKey().toString() + " will run at: " + scheduleTime2 + " and repeat: " + trigger2.getRepeatCount()
-
+ " times, every " + trigger2.getRepeatInterval() / 1000 + " seconds");
-
-
log.info("------- Starting Scheduler ----------------");
-
-
// All of the jobs have been added to the scheduler, but none of the jobs
-
// will run until the scheduler has been started
-
sched.start();
-
-
log.info("------- Started Scheduler -----------------");
-
-
log.info("------- Waiting 60 seconds... -------------");
-
try {
-
// wait five minutes to show jobs
-
Thread.sleep(60L * 1000L);
-
// executing...
-
} catch (Exception e) {
-
//
-
}
-
-
log.info("------- Shutting Down ---------------------");
-
-
sched.shutdown(true);
-
-
log.info("------- Shutdown Complete -----------------");
-
-
SchedulerMetaData metaData = sched.getMetaData();
-
log.info("Executed " + metaData.getNumberOfJobsExecuted() + " jobs.");
-
-
}
关于有状态的JOB。
job1是red,job2是green ,每个job每10秒执行一次,那么假如一个任务需要执行35秒呢?下一次执行在什么时候?
答:按照 trigger 的规则,第 20 秒和第 30 秒分别会有一次预定的触发执行,但是由于是有状态任务,因此实际不会被触发。在第 35秒第一次任务执行完毕时,Quartz 会把第 20秒 和第 30秒的两次触发作为 misfired job 进行处理。对于 misfired job,Quartz 会查看其 misfire 策略是如何设定的,如果是立刻执行,则会马上启动一次执行,如果是等待下次执行,则会忽略错过的任务,而等待下次(即第 6 分钟)触发执行。
有状态的job如果第一次没有执行完,第二次执行的时间错过了,就会被认为是misfire
doUpdateOfMisfiredTrigger调用CronTriggerImpl的updateAfterMisfire方法。
如果misfire设置为MISFIRE_INSTRUCTION_SMART_POLICY或MISFIRE_INSTRUCTION_FIRE_ONCE_NOW就是马上执行。
如果misfire设置为MISFIRE_INSTRUCTION_DO_NOTHING则在下一个周期再执行。
默认是:MISFIRE_INSTRUCTION_SMART_POLICY
可以通过trigger的build方法增加参数实现:
withMisfireHandlingInstructionFireAndProceed().build()
withMisfireHandlingInstructionDoNothing().build()
example5: Job Misfire
|
Class Name
|
Description
|
|
MisfireExample
|
主程序
|
|
StatefulDumbJob
|
每10秒执行一次
|
JOB1:每3秒执行一次,执行的任务是延时10秒的。statefulJob是有状态的,上一个任务没执行完,是不会执行的。
-
JobDetail job = newJob(StatefulDumbJob.class)
-
.withIdentity("statefulJob1", "group1")
-
.usingJobData(StatefulDumbJob.EXECUTION_DELAY, 10000L)
-
.build();
-
-
SimpleTrigger trigger = newTrigger()
-
.withIdentity("trigger1", "group1")
-
.startAt(startTime)
-
.withSchedule(simpleSchedule()
-
.withIntervalInSeconds(3)
-
.repeatForever())
-
.build();
-
-
sched.scheduleJob(job, trigger);
JOB2:对于misfire的任务设置为马上执行。默认是smart智能执行。在不同的情况下是不一样的。在Cron情况下都是立即执行。
-
job = newJob(StatefulDumbJob.class)
-
.withIdentity("statefulJob2", "group1")
-
.usingJobData(StatefulDumbJob.EXECUTION_DELAY, 10000L)
-
.build();
-
-
trigger = newTrigger()
-
.withIdentity("trigger2", "group1")
-
.startAt(startTime)
-
.withSchedule(simpleSchedule()
-
.withIntervalInSeconds(3)
-
.repeatForever()
-
.withMisfireHandlingInstructionNowWithExistingCount()) // set misfire instruction
-
.build();
对于SimpleTriggerImpl的MISFIRE_INSTRUCTION_SMART_POLICY
-
if (instr == Trigger.MISFIRE_INSTRUCTION_SMART_POLICY) {
-
if (getRepeatCount() == 0) {
-
instr = MISFIRE_INSTRUCTION_FIRE_NOW;
-
} else if (getRepeatCount() == REPEAT_INDEFINITELY) {
-
instr = MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT;
-
} else {
-
// if (getRepeatCount() > 0)
-
instr = MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT;
-
}
-
}
对于对于CronTriggerImpl的MISFIRE_INSTRUCTION_SMART_POLICY
-
if (instr == MISFIRE_INSTRUCTION_SMART_POLICY) {
-
instr = MISFIRE_INSTRUCTION_FIRE_ONCE_NOW;
-
}
example6: Dealing with Job Exceptions
在JOB1中如果出现异常了,可以通过抛出异常的方式来重新执行一次。
-
try {
-
int zero = 0;
-
int calculation = 4815 / zero;
-
}
-
catch (Exception e) {
-
_log.info("--- Error in job!");
-
JobExecutionException e2 =
-
new JobExecutionException(e);
-
// this job will refire immediately
-
e2.refireImmediately();
-
throw e2;
-
}
在JOB2中如果出现异常了,可以终止这个任务,以后也不再执行。
-
try {
-
int zero = 0;
-
int calculation = 4815 / zero;
-
}
-
catch (Exception e) {
-
_log.info("--- Error in job!");
-
JobExecutionException e2 =
-
new JobExecutionException(e);
-
// Quartz will automatically unschedule
-
// all triggers associated with this job
-
// so that it does not run again
-
e2.setUnscheduleAllTriggers(true);
-
throw e2;
-
}
example7:Interrupting Jobs
|
Class Name
|
Description
|
|
InterruptExample
|
主程序
|
|
DumbInterruptableJob
|
可中断JOB,4秒时间,for循环可以被中断
|
JOB实现InterruptableJob接口,实现中断逻辑。
-
public void interrupt() throws UnableToInterruptJobException {
-
_log.info("---" + _jobKey + " -- INTERRUPTING --");
-
_interrupted = true;
-
}
JOB在for循环中,可以被中断执行。
-
for (int i = 0; i < 4; i++) {
-
try {
-
Thread.sleep(1000L);
-
} catch (Exception ignore) {
-
ignore.printStackTrace();
-
}
-
-
// periodically check if we've been interrupted...
-
if(_interrupted) {
-
_log.info("--- " + _jobKey + " -- Interrupted... bailing out!");
-
return; // could also choose to throw a JobExecutionException
-
// if that made for sense based on the particular
-
// job's responsibilities/behaviors
-
}
-
}
主程序trigger每5秒触发执行。每7秒触发中断。
由代码sched.interrupt()看出来中断只针对当前sched实例,不是针对集群的。如果是集群,需要每个实例都触发。
-
for (int i = 0; i < 50; i++) {
-
try {
-
Thread.sleep(7000L);
-
// tell the scheduler to interrupt our job
-
sched.interrupt(job.getKey());
-
} catch (Exception e) {
-
//
-
}
-
}
-
for (int i = 0; i < 50; i++) {
-
try {
-
Thread.sleep(7000L);
-
// tell the scheduler to interrupt our job
-
sched.interrupt(job.getKey());
-
} catch (Exception e) {
-
//
-
}
-
}
example8:Fun with Calendars
可以设置一年内的某几天不执行。
-
// Add the holiday calendar to the schedule
-
AnnualCalendar holidays = new AnnualCalendar();
-
-
// fourth of July (July 4)
-
Calendar fourthOfJuly = new GregorianCalendar(2005, 6, 4);
-
holidays.setDayExcluded(fourthOfJuly, true);
-
// halloween (Oct 31)
-
Calendar halloween = new GregorianCalendar(2005, 9, 31);
-
holidays.setDayExcluded(halloween, true);
-
// christmas (Dec 25)
-
Calendar christmas = new GregorianCalendar(2005, 11, 25);
-
holidays.setDayExcluded(christmas, true);
-
-
// tell the schedule about our holiday calendar
-
sched.addCalendar("holidays", holidays, false, false);
-
-
// schedule a job to run hourly, starting on halloween
-
// at 10 am
-
Date runDate = dateOf(0, 0, 10, 31, 10);
-
-
JobDetail job = newJob(SimpleJob.class).withIdentity("job1", "group1").build();
-
-
SimpleTrigger trigger = newTrigger().withIdentity("trigger1", "group1").startAt(runDate)
-
.withSchedule(simpleSchedule().withIntervalInHours(1).repeatForever()).modifiedByCalendar("holidays").build();
-
-
// schedule the job and print the first run date
-
Date firstRunTime = sched.scheduleJob(job, trigger);
example9:Job Listeners
通过监听器可以用于日志、报表的处理。
也可以通过JOB监听器实现在JOB执行前后调用其它JOB,实现简单的任务流程。
监听器需要实现接口JobListener,可以实现jobExecutionVetoed,jobToBeExecuted,jobWasExecuted
代表执行失败、准备执行、执行成功。quartz在JobRunShell类中,在线程执行前后触发调用加入监听器的方法。
-
public class Job1Listener implements JobListener {
-
-
private static Logger _log = LoggerFactory.getLogger(Job1Listener.class);
-
-
public String getName() {
-
return "job1_to_job2";
-
}
-
-
public void jobToBeExecuted(JobExecutionContext inContext) {
-
_log.info("Job1Listener says: Job Is about to be executed.");
-
}
-
-
public void jobExecutionVetoed(JobExecutionContext inContext) {
-
_log.info("Job1Listener says: Job Execution was vetoed.");
-
}
-
-
public void jobWasExecuted(JobExecutionContext inContext, JobExecutionException inException) {
-
_log.info("Job1Listener says: Job was executed.");
-
-
// Simple job #2
-
JobDetail job2 = newJob(SimpleJob2.class).withIdentity("job2").build();
-
-
Trigger trigger = newTrigger().withIdentity("job2Trigger").startNow().build();
-
-
try {
-
// schedule the job to run!
-
inContext.getScheduler().scheduleJob(job2, trigger);
-
} catch (SchedulerException e) {
-
_log.warn("Unable to schedule job2!");
-
e.printStackTrace();
-
}
-
-
}
-
-
}
example10:Using Quartz Plug-Ins
插件的方式,是为了不对代码有太大的侵入。把JOB和trigger配置在xml文件上加载。好处是配置修改简单,不需要修改代码。
-
<job>
-
<name>TestJob2</name>
-
<group>GroupOfTestJob2</group>
-
<description>This is the description of TestJob2</description>
-
<job-class>org.quartz.examples.example10.SimpleJob</job-class>
-
<durability>false</durability>
-
<recover>true</recover>
-
<job-data-map>
-
<entry>
-
<key>someKey</key>
-
<value>someValue</value>
-
</entry>
-
<entry>
-
<key>someOtherKey</key>
-
<value>someOtherValue</value>
-
</entry>
-
</job-data-map>
-
</job>
-
-
<trigger>
-
<simple>
-
<name>TestSimpleTrigger2AtTenSecondIntervalAndFiveRepeats</name>
-
<group>GroupOfTestJob2Triggers</group>
-
<job-name>TestJob2</job-name>
-
<job-group>GroupOfTestJob2</job-group>
-
<start-time>2010-02-09T10:15:00</start-time>
-
<misfire-instruction>MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT</misfire-instruction>
-
<repeat-count>5</repeat-count>
-
<repeat-interval>10000</repeat-interval>
-
</simple>
-
</trigger>
example11:Quartz Under High Load
高负载,当线程池中的线程只有10个,而一次生成的定时任务是500个,不够用时执行任务是一个个执行。
而每个任务要延时0到2.5秒随机。11:58:40执行到11:59:46共用了60多秒。平均每个线程执行50个,每秒能执行不到1个。
当线程不够用时,执行的时间就是不准的。 所以需要监控线程池,线程不能满载超过30秒。

-
// schedule 500 jobs to run
-
for (int count = 1; count <= _numberOfJobs; count++) {
-
JobDetail job = newJob(SimpleJob.class).withIdentity("job" + count, "group_1").requestRecovery() // ask scheduler
-
// to re-execute
-
// this job if it
-
// was in
-
// progress when
-
// the scheduler
-
// went down...
-
.build();
-
-
// tell the job to delay some small amount... to simulate work...
-
long timeDelay = (long) (java.lang.Math.random() * 2500);
-
job.getJobDataMap().put(SimpleJob.DELAY_TIME, timeDelay);
-
-
Trigger trigger = newTrigger().withIdentity("trigger_" + count, "group_1")
-
.startAt(futureDate((10000 + (count * 100)), IntervalUnit.MILLISECOND)) // space fire times a small bit
-
.build();
-
-
sched.scheduleJob(job, trigger);
-
if (count % 25 == 0) {
-
log.info("...scheduled " + count + " jobs");
-
}
-
}
requestRecovery的作用在于当scheduler要down了,而任务正在执行时。可以通过scheduler重新执行。
example12:Remote Job Scheduling using RMI
客户端注册JOB和trigger,由服务端执行。客户端和服务端通过RMI通信。
参考:http://www.blogjava.net/xiaohuzi2008/archive/2012/12/04/392408.html
example13: Clustered Quartz
Quartz集群,通过数据库集群。
example14: Trigger Priorities
优先级1-10,优先级越高则同一时间点先执行。
example15: TC Clustered Quartz
基于Terracotta的内存级别的集群。对于大量小任务时使用。
|
Class Name
|
Description
|
|
ClusterExample
|
主程序
|
SimpleRecoveryJob
SimpleRecoveryStatefulJob
|
|
ClusterExample:
JOB1执行SimpleRecoveryJob每5秒执行一次,共执行21次
JOB2执行SimpleRecoveryJob每5秒执行一次,共执行21次
JOB3执行SimpleRecoveryStatefulJob每3秒执行一次,共执行21次
JOB4执行SimpleRecoveryJob每4秒执行一次,共执行21次
JOB5执行SimpleRecoveryJob每4.5秒执行一次,共执行21次
SimpleRecoveryJob与SimpleRecoveryStatefulJob都是延时执行10秒。
先instance2.bat设置启动参数为:
org.quartz.examples.example15.ClusterExample dontScheduleJobs
就是instance2不加JOB,只由instance1加的JOB,然后instance1与instance2共同运行,以集群的方式运行。
每次循环只会在一个实例上运行。
图1:在instance1上打印

图2:在instance1上打印

图3:在instance2上打印

再看一下job3是StatefulJob,必须在上一次执行完后才能触发。trigger3秒钟触发一次,但是job的执行需要10秒
所以效果就是10秒中执行一次。都是在实例1上执行。




如果instance2也有自己新增的job和trigger的话,instance1与instance2上新增的JOB在集群是共享的。

----
关于terracotta的使用、集群配置、持久化配置、quartz中的源码分析请访问:
http://blog.itpub.net/11627468/viewspace-1771336/
[INFO] 20 八月 09:26:09.842 上午 main [org.terracotta.quartz.DefaultClusteredJob
Store]
Synchronous write locking is [false]
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/11627468/viewspace-1774071/
,如需转载,请注明出处,否则将追究法律责任。