quartz详解5:官网example分析

http://blog.itpub.net/11627468/viewspace-1774071/ 


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:

点击(此处)折叠或打开

  1. public class HelloJob implements Job {

  2.     private static Logger _log = LoggerFactory.getLogger(HelloJob.class);

  3.   
  4.     public HelloJob() {
  5.     }

  6.    
  7.     public void execute(JobExecutionContext context)
  8.         throws JobExecutionException {

  9.         // Say Hello to the World and display the date/time
  10.         _log.info("Hello World! - " + new Date());
  11.     }

  12. }
查上面代码,HelloJob只是一个很简单的定时任务,实现了Job接口,同时实现了execute方法,然后方法内打印了当前时间。

SimpleExample:

点击(此处)折叠或打开


  1.  
  2. package org.quartz.examples.example1;

  3. import static org.quartz.DateBuilder.evenMinuteDate;
  4. import static org.quartz.JobBuilder.newJob;
  5. import static org.quartz.TriggerBuilder.newTrigger;

  6. import org.quartz.JobDetail;
  7. import org.quartz.Scheduler;
  8. import org.quartz.SchedulerFactory;
  9. import org.quartz.Trigger;
  10. import org.quartz.impl.StdSchedulerFactory;
  11. import org.slf4j.Logger;
  12. import org.slf4j.LoggerFactory;

  13. import java.util.Date;

  14. /**
  15.  * This Example will demonstrate how to start and shutdown the Quartz scheduler and how to schedule a job to run in
  16.  * Quartz.
  17.  * 
  18.  * @author Bill Kratzer
  19.  */
  20. public class SimpleExample {

  21.   public void run() throws Exception {
  22.     Logger log = LoggerFactory.getLogger(SimpleExample.class);

  23.     log.info("------- Initializing ----------------------");

  24.     // First we must get a reference to a scheduler
  25.     SchedulerFactory sf = new StdSchedulerFactory();
  26.     Scheduler sched = sf.getScheduler();

  27.     log.info("------- Initialization Complete -----------");

  28.     // computer a time that is on the next round minute
  29.     Date runTime = evenMinuteDate(new Date());

  30.     log.info("------- Scheduling Job -------------------");

  31.     // define the job and tie it to our HelloJob class
  32.     JobDetail job = newJob(HelloJob.class).withIdentity("job1", "group1").build();

  33.     // Trigger the job to run on the next round minute
  34.     Trigger trigger = newTrigger().withIdentity("trigger1", "group1").startAt(runTime).build();

  35.     // Tell quartz to schedule the job using our trigger
  36.     sched.scheduleJob(job, trigger);
  37.     log.info(job.getKey() + " will run at: " + runTime);

  38.     // Start up the scheduler (nothing can actually run until the
  39.     // scheduler has been started)
  40.     sched.start();

  41.     log.info("------- Started Scheduler -----------------");

  42.     // wait long enough so that the scheduler as an opportunity to
  43.     // run the job!
  44.     log.info("------- Waiting 65 seconds... -------------");
  45.     try {
  46.       // wait 65 seconds to show job
  47.       Thread.sleep(65L * 1000L);
  48.       // executing...
  49.     } catch (Exception e) {
  50.       //
  51.     }

  52.     // shut down the scheduler
  53.     log.info("------- Shutting Down ---------------------");
  54.     sched.shutdown(true);
  55.     log.info("------- Shutdown Complete -----------------");
  56.   }

  57.   public static void main(String[] args) throws Exception {

  58.     SimpleExample example = new SimpleExample();
  59.     example.run();

  60.   }

  61. }
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:一个简单的任务,打印当前时间
Simple Job:

点击(此处)折叠或打开

  1. public void execute(JobExecutionContext context)
  2.         throws JobExecutionException {

  3.         // This job simply prints out its job name and the
  4.         // date and time that it is running
  5.         JobKey jobKey = context.getJobDetail().getKey();
  6.         _log.info("SimpleJob says: " + jobKey + " executing at " + new Date());
  7.     }
SimpleTriggerExa mple:

点击(此处)折叠或打开

  1. /* 
  2.  * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); you may not 
  5.  * use this file except in compliance with the License. You may obtain a copy 
  6.  * of the License at 
  7.  * 
  8.  * http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
  12.  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 
  13.  * License for the specific language governing permissions and limitations 
  14.  * under the License.
  15.  * 
  16.  */
  17.  
  18. package org.quartz.examples.example2;

  19. import static org.quartz.DateBuilder.futureDate;
  20. import static org.quartz.JobBuilder.newJob;
  21. import static org.quartz.JobKey.jobKey;
  22. import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
  23. import static org.quartz.TriggerBuilder.newTrigger;

  24. import org.quartz.DateBuilder;
  25. import org.quartz.DateBuilder.IntervalUnit;
  26. import org.quartz.JobDetail;
  27. import org.quartz.Scheduler;
  28. import org.quartz.SchedulerFactory;
  29. import org.quartz.SchedulerMetaData;
  30. import org.quartz.SimpleTrigger;
  31. import org.quartz.impl.StdSchedulerFactory;
  32. import org.slf4j.Logger;
  33. import org.slf4j.LoggerFactory;

  34. import java.util.Date;

  35. /**
  36.  * This Example will demonstrate all of the basics of scheduling capabilities of Quartz using Simple Triggers.
  37.  * 
  38.  * @author Bill Kratzer
  39.  */
  40. public class SimpleTriggerExample {

  41.   public void run() throws Exception {
  42.     Logger log = LoggerFactory.getLogger(SimpleTriggerExample.class);

  43.     log.info("------- Initializing -------------------");

  44.     // First we must get a reference to a scheduler
  45.     SchedulerFactory sf = new StdSchedulerFactory();
  46.     Scheduler sched = sf.getScheduler();

  47.     log.info("------- Initialization Complete --------");

  48.     log.info("------- Scheduling Jobs ----------------");

  49.     // jobs can be scheduled before sched.start() has been called

  50.     // get a "nice round" time a few seconds in the future...
  51.     Date startTime = DateBuilder.nextGivenSecondDate(null, 15);

  52.     // job1 will only fire once at date/time "ts"
  53.     JobDetail job = newJob(SimpleJob.class).withIdentity("job1", "group1").build();

  54.     SimpleTrigger trigger = (SimpleTrigger) newTrigger().withIdentity("trigger1", "group1").startAt(startTime).build();

  55.     // schedule it to run!
  56.     Date ft = sched.scheduleJob(job, trigger);
  57.     log.info(job.getKey() + " will run at: " + ft + " and repeat: " + trigger.getRepeatCount() + " times, every "
  58.              + trigger.getRepeatInterval() / 1000 + " seconds");

  59.     // job2 will only fire once at date/time "ts"
  60.     job = newJob(SimpleJob.class).withIdentity("job2", "group1").build();

  61.     trigger = (SimpleTrigger) newTrigger().withIdentity("trigger2", "group1").startAt(startTime).build();

  62.     ft = sched.scheduleJob(job, trigger);
  63.     log.info(job.getKey() + " will run at: " + ft + " and repeat: " + trigger.getRepeatCount() + " times, every "
  64.              + trigger.getRepeatInterval() / 1000 + " seconds");

  65.     // job3 will run 11 times (run once and repeat 10 more times)
  66.     // job3 will repeat every 10 seconds
  67.     job = newJob(SimpleJob.class).withIdentity("job3", "group1").build();

  68.     trigger = newTrigger().withIdentity("trigger3", "group1").startAt(startTime)
  69.         .withSchedule(simpleSchedule().withIntervalInSeconds(10).withRepeatCount(10)).build();

  70.     ft = sched.scheduleJob(job, trigger);
  71.     log.info(job.getKey() + " will run at: " + ft + " and repeat: " + trigger.getRepeatCount() + " times, every "
  72.              + trigger.getRepeatInterval() / 1000 + " seconds");

  73.     // the same job (job3) will be scheduled by a another trigger
  74.     // this time will only repeat twice at a 70 second interval

  75.     trigger = newTrigger().withIdentity("trigger3", "group2").startAt(startTime)
  76.         .withSchedule(simpleSchedule().withIntervalInSeconds(10).withRepeatCount(2)).forJob(job).build();

  77.     ft = sched.scheduleJob(trigger);
  78.     log.info(job.getKey() + " will [also] run at: " + ft + " and repeat: " + trigger.getRepeatCount()
  79.              + " times, every " + trigger.getRepeatInterval() / 1000 + " seconds");

  80.     // job4 will run 6 times (run once and repeat 5 more times)
  81.     // job4 will repeat every 10 seconds
  82.     job = newJob(SimpleJob.class).withIdentity("job4", "group1").build();

  83.     trigger = newTrigger().withIdentity("trigger4", "group1").startAt(startTime)
  84.         .withSchedule(simpleSchedule().withIntervalInSeconds(10).withRepeatCount(5)).build();

  85.     ft = sched.scheduleJob(job, trigger);
  86.     log.info(job.getKey() + " will run at: " + ft + " and repeat: " + trigger.getRepeatCount() + " times, every "
  87.              + trigger.getRepeatInterval() / 1000 + " seconds");

  88.     // job5 will run once, five minutes in the future
  89.     job = newJob(SimpleJob.class).withIdentity("job5", "group1").build();

  90.     trigger = (SimpleTrigger) newTrigger().withIdentity("trigger5", "group1")
  91.         .startAt(futureDate(5, IntervalUnit.MINUTE)).build();

  92.     ft = sched.scheduleJob(job, trigger);
  93.     log.info(job.getKey() + " will run at: " + ft + " and repeat: " + trigger.getRepeatCount() + " times, every "
  94.              + trigger.getRepeatInterval() / 1000 + " seconds");

  95.     // job6 will run indefinitely, every 40 seconds
  96.     job = newJob(SimpleJob.class).withIdentity("job6", "group1").build();

  97.     trigger = newTrigger().withIdentity("trigger6", "group1").startAt(startTime)
  98.         .withSchedule(simpleSchedule().withIntervalInSeconds(40).repeatForever()).build();

  99.     ft = sched.scheduleJob(job, trigger);
  100.     log.info(job.getKey() + " will run at: " + ft + " and repeat: " + trigger.getRepeatCount() + " times, every "
  101.              + trigger.getRepeatInterval() / 1000 + " seconds");

  102.     log.info("------- Starting Scheduler ----------------");

  103.     // All of the jobs have been added to the scheduler, but none of the jobs
  104.     // will run until the scheduler has been started
  105.     sched.start();

  106.     log.info("------- Started Scheduler -----------------");

  107.     // jobs can also be scheduled after start() has been called...
  108.     // job7 will repeat 20 times, repeat every five minutes
  109.     job = newJob(SimpleJob.class).withIdentity("job7", "group1").build();

  110.     trigger = newTrigger().withIdentity("trigger7", "group1").startAt(startTime)
  111.         .withSchedule(simpleSchedule().withIntervalInMinutes(5).withRepeatCount(20)).build();

  112.     ft = sched.scheduleJob(job, trigger);
  113.     log.info(job.getKey() + " will run at: " + ft + " and repeat: " + trigger.getRepeatCount() + " times, every "
  114.              + trigger.getRepeatInterval() / 1000 + " seconds");

  115.     // jobs can be fired directly... (rather than waiting for a trigger)
  116.     job = newJob(SimpleJob.class).withIdentity("job8", "group1").storeDurably().build();

  117.     sched.addJob(job, true);

  118.     log.info("'Manually' triggering job8...");
  119.     sched.triggerJob(jobKey("job8", "group1"));

  120.     log.info("------- Waiting 30 seconds... --------------");

  121.     try {
  122.       // wait 33 seconds to show jobs
  123.       Thread.sleep(30L * 1000L);
  124.       // executing...
  125.     } catch (Exception e) {
  126.       //
  127.     }

  128.     // jobs can be re-scheduled...
  129.     // job 7 will run immediately and repeat 10 times for every second
  130.     log.info("------- Rescheduling... --------------------");
  131.     trigger = newTrigger().withIdentity("trigger7", "group1").startAt(startTime)
  132.         .withSchedule(simpleSchedule().withIntervalInMinutes(5).withRepeatCount(20)).build();

  133.     ft = sched.rescheduleJob(trigger.getKey(), trigger);
  134.     log.info("job7 rescheduled to run at: " + ft);

  135.     log.info("------- Waiting five minutes... ------------");
  136.     try {
  137.       // wait five minutes to show jobs
  138.       Thread.sleep(300L * 1000L);
  139.       // executing...
  140.     } catch (Exception e) {
  141.       //
  142.     }

  143.     log.info("------- Shutting Down ---------------------");

  144.     sched.shutdown(true);

  145.     log.info("------- Shutdown Complete -----------------");

  146.     // display some stats about the schedule that just ran
  147.     SchedulerMetaData metaData = sched.getMetaData();
  148.     log.info("Executed " + metaData.getNumberOfJobsExecuted() + " jobs.");

  149.   }

  150.   public static void main(String[] args) throws Exception {

  151.     SimpleTriggerExample example = new SimpleTriggerExample();
  152.     example.run();

  153.   }

  154. }
job3每10秒执行1次,重复10次,一共执行11次。

点击(此处)折叠或打开

  1. // job3 will run 11 times (run once and repeat 10 more times)
  2.     // job3 will repeat every 10 seconds
  3.     job = newJob(SimpleJob.class).withIdentity("job3", "group1").build();

  4.     trigger = newTrigger().withIdentity("trigger3", "group1").startAt(startTime)
  5.         .withSchedule(simpleSchedule().withIntervalInSeconds(10).withRepeatCount(10)).build();
同样是job3,新增一个trigger来触发它。
因为在版本2.2.1中,是可以支持多个trigger来对应触发同一个JOB的。

点击(此处)折叠或打开

  1. trigger = newTrigger().withIdentity("trigger3", "group2").startAt(startTime)
  2.         .withSchedule(simpleSchedule().withIntervalInSeconds(10).withRepeatCount(2)).forJob(job).build();
job5也可以设置5分钟后执行:

点击(此处)折叠或打开

  1. // job5 will run once, five minutes in the future
  2.     job = newJob(SimpleJob.class).withIdentity("job5", "group1").build();

  3.     trigger = (SimpleTrigger) newTrigger().withIdentity("trigger5", "group1")
  4.         .startAt(futureDate(5, IntervalUnit.MINUTE)).build();
job6设置每40秒执行,一直执行:

点击(此处)折叠或打开

扫描二维码关注公众号,回复: 1803115 查看本文章
  1. job = newJob(SimpleJob.class).withIdentity("job6", "group1").build();

  2.     trigger = newTrigger().withIdentity("trigger6", "group1").startAt(startTime)
  3.         .withSchedule(simpleSchedule().withIntervalInSeconds(40).repeatForever()).build();
job7是可以在scheduler启动后再创建,加入到scheduler中。
job8表示,不需要创建trigger,可以直接触发任务。




example3:Cron Trigger
job1是每20秒执行一次:

点击(此处)折叠或打开

  1. JobDetail job = newJob(SimpleJob.class)
  2.     .withIdentity("job1", "group1")
  3.     .build();

  4. CronTrigger trigger = newTrigger()
  5.     .withIdentity("trigger1", "group1")
  6.     .withSchedule(cronSchedule("0/20 * * * * ?"))
  7.     .build();

  8. sched.scheduleJob(job, trigger);
Jo2是每2分钟执行一次,在15秒这个点执行。如1分15秒,3分15秒,5分15秒。

点击(此处)折叠或打开

  1. JobDetail job = newJob(SimpleJob.class)
  2.     .withIdentity("job1", "group1")
  3.     .build();

  4. CronTrigger trigger = newTrigger()
  5.     .withIdentity("trigger1", "group1")
  6.     .withSchedule(cronSchedule("0/20 * * * * ?"))
  7.     .build();

  8. sched.scheduleJob(job, trigger);
JOB3是每2分种的整点执行一次,在上午8点到下午17点之间。

点击(此处)折叠或打开

  1. // job 3 will run every other minute but only between 8am and 5pm
  2.     job = newJob(SimpleJob.class).withIdentity("job3", "group1").build();

  3.     trigger = newTrigger().withIdentity("trigger3", "group1").withSchedule(cronSchedule("0 0/2 8-17 * * ?")).build();

  4.     ft = sched.scheduleJob(job, trigger);
  5.     log.info(job.getKey() + " has been scheduled to run at: " + ft + " and repeat based on expression: "
  6.              + trigger.getCronExpression());
JOB5在每个月1号和15号的上午10点执行:

点击(此处)折叠或打开

  1. // job 5 will run at 10am on the 1st and 15th days of the month
  2.     job = newJob(SimpleJob.class).withIdentity("job5", "group1").build();

  3.     trigger = newTrigger().withIdentity("trigger5", "group1").withSchedule(cronSchedule("0 0 10am 1,15 * ?")).build();

  4.     ft = sched.scheduleJob(job, trigger);
  5.     log.info(job.getKey() + " has been scheduled to run at: " + ft + " and repeat based on expression: "
  6.              + 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...

点击(此处)折叠或打开

  1. @PersistJobDataAfterExecution
  2. @DisallowConcurrentExecution
  3. public class ColorJob implements Job {

看一下例子:

点击(此处)折叠或打开

  1. public class JobStateExample {

  2.   public void run() throws Exception {
  3.     Logger log = LoggerFactory.getLogger(JobStateExample.class);

  4.     log.info("------- Initializing -------------------");

  5.     // First we must get a reference to a scheduler
  6.     SchedulerFactory sf = new StdSchedulerFactory();
  7.     Scheduler sched = sf.getScheduler();

  8.     log.info("------- Initialization Complete --------");

  9.     log.info("------- Scheduling Jobs ----------------");

  10.     // get a "nice round" time a few seconds in the future....
  11.     Date startTime = nextGivenSecondDate(null, 10);

  12.     // job1 will only run 5 times (at start time, plus 4 repeats), every 10 seconds
  13.     JobDetail job1 = newJob(ColorJob.class).withIdentity("job1", "group1").build();

  14.     SimpleTrigger trigger1 = newTrigger().withIdentity("trigger1", "group1").startAt(startTime)
  15.         .withSchedule(simpleSchedule().withIntervalInSeconds(10).withRepeatCount(4)).build();

  16.     // pass initialization parameters into the job
  17.     job1.getJobDataMap().put(ColorJob.FAVORITE_COLOR, "Green");
  18.     job1.getJobDataMap().put(ColorJob.EXECUTION_COUNT, 1);

  19.     // schedule the job to run
  20.     Date scheduleTime1 = sched.scheduleJob(job1, trigger1);
  21.     log.info(job1.getKey() + " will run at: " + scheduleTime1 + " and repeat: " + trigger1.getRepeatCount()
  22.              + " times, every " + trigger1.getRepeatInterval() / 1000 + " seconds");

  23.     // job2 will also run 5 times, every 10 seconds
  24.     JobDetail job2 = newJob(ColorJob.class).withIdentity("job2", "group1").build();

  25.     SimpleTrigger trigger2 = newTrigger().withIdentity("trigger2", "group1").startAt(startTime)
  26.         .withSchedule(simpleSchedule().withIntervalInSeconds(10).withRepeatCount(4)).build();

  27.     // pass initialization parameters into the job
  28.     // this job has a different favorite color!
  29.     job2.getJobDataMap().put(ColorJob.FAVORITE_COLOR, "Red");
  30.     job2.getJobDataMap().put(ColorJob.EXECUTION_COUNT, 1);

  31.     // schedule the job to run
  32.     Date scheduleTime2 = sched.scheduleJob(job2, trigger2);
  33.     log.info(job2.getKey().toString() + " will run at: " + scheduleTime2 + " and repeat: " + trigger2.getRepeatCount()
  34.              + " times, every " + trigger2.getRepeatInterval() / 1000 + " seconds");

  35.     log.info("------- Starting Scheduler ----------------");

  36.     // All of the jobs have been added to the scheduler, but none of the jobs
  37.     // will run until the scheduler has been started
  38.     sched.start();

  39.     log.info("------- Started Scheduler -----------------");

  40.     log.info("------- Waiting 60 seconds... -------------");
  41.     try {
  42.       // wait five minutes to show jobs
  43.       Thread.sleep(60L * 1000L);
  44.       // executing...
  45.     } catch (Exception e) {
  46.       //
  47.     }

  48.     log.info("------- Shutting Down ---------------------");

  49.     sched.shutdown(true);

  50.     log.info("------- Shutdown Complete -----------------");

  51.     SchedulerMetaData metaData = sched.getMetaData();
  52.     log.info("Executed " + metaData.getNumberOfJobsExecuted() + " jobs.");

  53.   }
关于有状态的JOB。
job1是red,job2是green ,每个job每10秒执行一次,那么假如一个任务需要执行3 5 秒呢?下一次执行在什么时候?
答: 按照 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是有状态的,上一个任务没执行完,是不会执行的。

点击(此处)折叠或打开

  1. JobDetail job = newJob(StatefulDumbJob.class)
  2.     .withIdentity("statefulJob1", "group1")
  3.     .usingJobData(StatefulDumbJob.EXECUTION_DELAY, 10000L)
  4.     .build();

  5. SimpleTrigger trigger = newTrigger() 
  6.     .withIdentity("trigger1", "group1")
  7.     .startAt(startTime)
  8.     .withSchedule(simpleSchedule()
  9.             .withIntervalInSeconds(3)
  10.             .repeatForever())
  11.     .build();

  12. sched.scheduleJob(job, trigger);
JOB2:对于misfire的任务设置为马上执行。默认是smart智能执行。在不同的情况下是不一样的。在Cron情况下都是立即执行。

点击(此处)折叠或打开

  1. job = newJob(StatefulDumbJob.class)
  2.             .withIdentity("statefulJob2", "group1")
  3.             .usingJobData(StatefulDumbJob.EXECUTION_DELAY, 10000L)
  4.             .build();
  5.     
  6.         trigger = newTrigger() 
  7.             .withIdentity("trigger2", "group1")
  8.             .startAt(startTime)
  9.             .withSchedule(simpleSchedule()
  10.                     .withIntervalInSeconds(3)
  11.                     .repeatForever()
  12.                     .withMisfireHandlingInstructionNowWithExistingCount()) // set misfire instruction
  13.             .build();
对于SimpleTriggerImpl的 MISFIRE_INSTRUCTION_SMART_POLICY

点击(此处)折叠或打开

  1. if (instr == Trigger.MISFIRE_INSTRUCTION_SMART_POLICY) {
  2.             if (getRepeatCount() == 0) {
  3.                 instr = MISFIRE_INSTRUCTION_FIRE_NOW;
  4.             } else if (getRepeatCount() == REPEAT_INDEFINITELY) {
  5.                 instr = MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT;
  6.             } else {
  7.                 // if (getRepeatCount() > 0)
  8.                 instr = MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT;
  9.             }
  10.         }
对于 对于CronTriggerImpl的 MISFIRE_INSTRUCTION_SMART_POLICY

点击(此处)折叠或打开

  1. if (instr == MISFIRE_INSTRUCTION_SMART_POLICY) {
  2.             instr = MISFIRE_INSTRUCTION_FIRE_ONCE_NOW;
  3.         }

example6   Dealing with Job Exceptions
在JOB1中如果出现异常了,可以通过抛出异常的方式来重新执行一次。

点击(此处)折叠或打开

  1. try {
  2.             int zero = 0;
  3.             int calculation = 4815 / zero;
  4.         } 
  5.         catch (Exception e) {
  6.             _log.info("--- Error in job!");
  7.             JobExecutionException e2 = 
  8.                 new JobExecutionException(e);
  9.             // this job will refire immediately
  10.             e2.refireImmediately();
  11.             throw e2;
  12.         }
在JOB2中如果出现异常了,可以终止这个任务,以后也不再执行。

点击(此处)折叠或打开

  1. try {
  2.             int zero = 0;
  3.             int calculation = 4815 / zero;
  4.         } 
  5.         catch (Exception e) {
  6.             _log.info("--- Error in job!");
  7.             JobExecutionException e2 = 
  8.                 new JobExecutionException(e);
  9.             // Quartz will automatically unschedule
  10.             // all triggers associated with this job
  11.             // so that it does not run again
  12.             e2.setUnscheduleAllTriggers(true);
  13.             throw e2;
  14.         }


example7 Interrupting Jobs  
Class Name Description
InterruptExample 主程序
DumbInterruptableJob 可中断JOB,4秒时间,for循环可以被中断
JOB实现InterruptableJob接口,实现中断逻辑。

点击(此处)折叠或打开

  1. public void interrupt() throws UnableToInterruptJobException {
  2.         _log.info("---" + _jobKey + " -- INTERRUPTING --");
  3.         _interrupted = true;
  4.     }
JOB在for循环中,可以被中断执行。

点击(此处)折叠或打开

  1. for (int i = 0; i < 4; i++) {
  2.                 try {
  3.                     Thread.sleep(1000L);
  4.                 } catch (Exception ignore) {
  5.                     ignore.printStackTrace();
  6.                 }
  7.                 
  8.                 // periodically check if we've been interrupted...
  9.                 if(_interrupted) {
  10.                     _log.info("--- " + _jobKey + " -- Interrupted... bailing out!");
  11.                     return; // could also choose to throw a JobExecutionException 
  12.                              // if that made for sense based on the particular 
  13.                              // job's responsibilities/behaviors
  14.                 }
  15.             }
主程序trigger每5秒触发执行。每7秒触发中断。
由代码sched.interrupt()看出来中断只针对当前sched实例,不是针对集群的。如果是集群,需要每个实例都触发。

点击(此处)折叠或打开

  1. for (int i = 0; i < 50; i++) {
  2.       try {
  3.         Thread.sleep(7000L);
  4.         // tell the scheduler to interrupt our job
  5.         sched.interrupt(job.getKey());
  6.       } catch (Exception e) {
  7.         //
  8.       }
  9.     }


点击(此处)折叠或打开

  1. for (int i = 0; i < 50; i++) {
  2.       try {
  3.         Thread.sleep(7000L);
  4.         // tell the scheduler to interrupt our job
  5.         sched.interrupt(job.getKey());
  6.       } catch (Exception e) {
  7.         //
  8.       }
  9.     }

example8 Fun with Calendars
可以设置一年内的某几天不执行。

点击(此处)折叠或打开

  1. // Add the holiday calendar to the schedule
  2.     AnnualCalendar holidays = new AnnualCalendar();

  3.     // fourth of July (July 4)
  4.     Calendar fourthOfJuly = new GregorianCalendar(2005, 6, 4);
  5.     holidays.setDayExcluded(fourthOfJuly, true);
  6.     // halloween (Oct 31)
  7.     Calendar halloween = new GregorianCalendar(2005, 9, 31);
  8.     holidays.setDayExcluded(halloween, true);
  9.     // christmas (Dec 25)
  10.     Calendar christmas = new GregorianCalendar(2005, 11, 25);
  11.     holidays.setDayExcluded(christmas, true);

  12.     // tell the schedule about our holiday calendar
  13.     sched.addCalendar("holidays", holidays, false, false);

  14.     // schedule a job to run hourly, starting on halloween
  15.     // at 10 am
  16.     Date runDate = dateOf(0, 0, 10, 31, 10);

  17.     JobDetail job = newJob(SimpleJob.class).withIdentity("job1", "group1").build();

  18.     SimpleTrigger trigger = newTrigger().withIdentity("trigger1", "group1").startAt(runDate)
  19.         .withSchedule(simpleSchedule().withIntervalInHours(1).repeatForever()).modifiedByCalendar("holidays").build();

  20.     // schedule the job and print the first run date
  21.     Date firstRunTime = sched.scheduleJob(job, trigger);
example9 Job Listeners
通过监听器可以用于日志、报表的处理。
也可以通过JOB监听器实现在JOB执行前后调用其它JOB,实现简单的任务流程。
监听器需要实现接口JobListener,可以实现jobExecutionVetoed,jobToBeExecuted,jobWasExecuted
代表执行失败、准备执行、执行成功。quartz在JobRunShell类中,在线程执行前后触发调用加入监听器的方法。

点击(此处)折叠或打开

  1. public class Job1Listener implements JobListener {

  2.   private static Logger _log = LoggerFactory.getLogger(Job1Listener.class);

  3.   public String getName() {
  4.     return "job1_to_job2";
  5.   }

  6.   public void jobToBeExecuted(JobExecutionContext inContext) {
  7.     _log.info("Job1Listener says: Job Is about to be executed.");
  8.   }

  9.   public void jobExecutionVetoed(JobExecutionContext inContext) {
  10.     _log.info("Job1Listener says: Job Execution was vetoed.");
  11.   }

  12.   public void jobWasExecuted(JobExecutionContext inContext, JobExecutionException inException) {
  13.     _log.info("Job1Listener says: Job was executed.");

  14.     // Simple job #2
  15.     JobDetail job2 = newJob(SimpleJob2.class).withIdentity("job2").build();

  16.     Trigger trigger = newTrigger().withIdentity("job2Trigger").startNow().build();

  17.     try {
  18.       // schedule the job to run!
  19.       inContext.getScheduler().scheduleJob(job2, trigger);
  20.     } catch (SchedulerException e) {
  21.       _log.warn("Unable to schedule job2!");
  22.       e.printStackTrace();
  23.     }

  24.   }

  25. }


example10 Using Quartz Plug-Ins
插件的方式,是为了不对代码有太大的侵入。把JOB和trigger配置在xml文件上加载。好处是配置修改简单,不需要修改代码。

点击(此处)折叠或打开

  1. <job>
  2.      <name>TestJob2</name>
  3.      <group>GroupOfTestJob2</group>
  4.      <description>This is the description of TestJob2</description>
  5.      <job-class>org.quartz.examples.example10.SimpleJob</job-class>
  6.      <durability>false</durability>
  7.      <recover>true</recover>
  8.      <job-data-map>
  9.      <entry>
  10.      <key>someKey</key>
  11.      <value>someValue</value>
  12.      </entry>
  13.      <entry>
  14.      <key>someOtherKey</key>
  15.      <value>someOtherValue</value>
  16.      </entry>
  17.      </job-data-map>
  18.      </job>
  19.      
  20.      <trigger>
  21.      <simple>
  22.      <name>TestSimpleTrigger2AtTenSecondIntervalAndFiveRepeats</name>
  23.      <group>GroupOfTestJob2Triggers</group>
  24.      <job-name>TestJob2</job-name>
  25.      <job-group>GroupOfTestJob2</job-group>
  26.      <start-time>2010-02-09T10:15:00</start-time>
  27.      <misfire-instruction>MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT</misfire-instruction>
  28.      <repeat-count>5</repeat-count>
  29.      <repeat-interval>10000</repeat-interval>
  30.      </simple>
  31.      </trigger>



example11 Quartz Under High Load
高负载,当线程池中的线程只有10个,而一次生成的定时任务是500个,不够用时执行任务是一个个执行。
而每个任务要延时0到2.5秒随机。11:58:40执行到11:59:46共用了60多秒。平均每个线程执行50个,每秒能执行不到1个。
当线程不够用时,执行的时间就是不准的。 所以需要监控线程池,线程不能满载超过30秒。

点击(此处)折叠或打开

  1. // schedule 500 jobs to run
  2.     for (int count = 1; count <= _numberOfJobs; count++) {
  3.       JobDetail job = newJob(SimpleJob.class).withIdentity("job" + count, "group_1").requestRecovery() // ask scheduler
  4.                                                                                                        // to re-execute
  5.                                                                                                        // this job if it
  6.                                                                                                        // was in
  7.                                                                                                        // progress when
  8.                                                                                                        // the scheduler
  9.                                                                                                        // went down...
  10.           .build();

  11.       // tell the job to delay some small amount... to simulate work...
  12.       long timeDelay = (long) (java.lang.Math.random() * 2500);
  13.       job.getJobDataMap().put(SimpleJob.DELAY_TIME, timeDelay);

  14.       Trigger trigger = newTrigger().withIdentity("trigger_" + count, "group_1")
  15.           .startAt(futureDate((10000 + (count * 100)), IntervalUnit.MILLISECOND)) // space fire times a small bit
  16.           .build();

  17.       sched.scheduleJob(job, trigger);
  18.       if (count % 25 == 0) {
  19.         log.info("...scheduled " + count + " jobs");
  20.       }
  21.     }


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

Cluster Example:
JOB1执行SimpleRecoveryJob每5秒执行一次,共执行21次
JOB2 执行 SimpleRecoveryJob 每5秒执行一次,共执行21次
JOB3 执行 SimpleRecoveryStatefulJob 每3秒执行一次,共执行21次
JOB4执行SimpleRecoveryJob每4秒执行一次,共执行21次
JOB5执行SimpleRecoveryJob每4.5秒执行一次,共执行21次

SimpleRecove ryJob与 SimpleRecov eryStatefulJob都是延时执行10秒。
先instance2.bat设置启动参数为:
org.quartz.examples.example15.ClusterExample  dontSche dule Jobs
就是instance2不加JOB,只由instance1加的JOB,然后instance1与instance2共同运行,以集群的方式运行。
每次循环只会在一个实例上运行。
图1:在instance1上打印

图2:在instance1上打印

图3:在instance2上打印


再看一下job3是 Sta tefulJob,必须在上一次执行完后才能触发。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]

猜你喜欢

转载自blog.csdn.net/u012506661/article/details/78553791