Quartz作业调度

来源:互联网 发布:数据库审计产品价格 编辑:程序博客网 时间:2024/05/16 11:56

 一、java.util.Timer
       在Java中有一个任务处理类java.util.Timer,非常方便于处理由时间触发的事件任务,只需建立一个继承java.util.TimerTask的子类,重载父类的run()方法实现具体的任务,然后调用Timer的public void schedule(TimerTask task, long delay, long period)方法实现任务的调度。

       但是这种方法只能实现简单的任务调度,不能满足任务调度时间比较复杂的需求。比如希望系统在每周的工作日的8:00时向系统用户给出一个提示,这种方法实现起来就困难了,还有更为复杂的任务调度时间要求。


二、Quartz

       OpenSymphony 的Quartz提供了一个比较完美的任务调度解决方案。
       Quartz 是个开源的作业调度框架,为在 Java 应用程序中进行作业调度提供了简单却强大的机制。
       Quartz中有两个基本概念:作业和触发器。作业是能够调度的可执行任务,触发器提供了对作业的调度。
 

1、作业
 
 实现 org.quartz.job 接口,实现接口方法 public void execute(JobExecutionContext context) throws JobExecutionException,在这个方法实现具体的作业任务。
代码例子:SimpleQuartzJob.java
 
package com.ibm.developerworks.quartz;
import java.util.Date;import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
 
public class SimpleQuartzJob implements Job {
 
    public SimpleQuartzJob() { }
    public void execute(JobExecutionContext context) throws JobExecutionException {
         System.out.println("In SimpleQuartzJob - executing its JOB at " + new Date() + " by " + context.getTrigger().getName());
   }
}
 
 execute 方法接受一个 JobExecutionContext 对象作为参数。这个对象提供了作业实例的运行时上下文。它提供了对调度器和触发器的访问,这两者协作来启动作业以及作业的 JobDetail 对象的执行。Quartz 通过把作业的状态放在 JobDetail 对象中并让 JobDetail 构造函数启动一个作业的实例,分离了作业的执行和作业周围的状态。JobDetail 对象储存作业的侦听器、群组、数据映射、描述以及作业的其他属性。
 
 
2、触发器
 
触发器可以实现对任务执行的调度。Quartz 提供了几种不同的触发器,复杂程度各不相同。
    
简单触发器:

public void task() throws SchedulerException {
  
  // Initiate a Schedule Factory
  SchedulerFactory schedulerFactory = new StdSchedulerFactory();
  
  // Retrieve a scheduler from schedule factory
  Scheduler scheduler = schedulerFactory.getScheduler();

  // current time
  long ctime = System.currentTimeMillis();

  // Initiate JobDetail with job name, job group, and executable job class
  JobDetail jobDetail = new JobDetail("jobDetail-s1",
    "jobDetailGroup-s1", SimpleQuartzJob.class);
  
  // Initiate SimpleTrigger with its name and group name
  SimpleTrigger simpleTrigger = new SimpleTrigger("simpleTrigger",
    "triggerGroup-s1");
  
  // set its start up time
  simpleTrigger.setStartTime(new Date(ctime));
  
  // set the interval, how often the job should run (10 seconds here)
  simpleTrigger.setRepeatInterval(10000);
  
  // set the number of execution of this job, set to 10 times.
  // It will run 10 time and exhaust.
  simpleTrigger.setRepeatCount(100);
  
  // set the ending time of this job.
  // We set it for 60 seconds from its startup time here
  // Even if we set its repeat count to 10,
  // this will stop its process after 6 repeats as it gets it endtime by
  // then.
  // simpleTrigger.setEndTime(new Date(ctime + 60000L));
  // set priority of trigger. If not set, the default is 5
  // simpleTrigger.setPriority(10);
  // schedule a job with JobDetail and Trigger
  scheduler.scheduleJob(jobDetail, simpleTrigger);

  // start the scheduler
  scheduler.start();
 }

首先实例化一个 SchedulerFactory,获得调度器。创建 JobDetail 对象时,它的构造函数要接受一个 Job 作为参数。SimpleTrigger 是一个简单的触发器。在创建对象之后,设置几个基本属性以立即调度任务,然后每 10 秒重复一次,直到作业被执行 100 次。

 

Cron触发器:

        CronTrigger 支持比SimpleTrigger 更具体强大的调度,实现起来却不是很复杂。CronTrigger基于cron 表达式,支持类似日历的重复间隔更为复杂的调度时间上的要求。Cron 表达式包括以下7 个字段:

  • 小时
  • 月内日期
  • 周内日期
  • 年(可选字段)

      Cron 触发器利用一系列特殊字符,如下所示:

一个Quartz的CronTrigger表达式分为七项子表达式,其中每一项以空格隔开,从左到右分别是:秒,分,时,月的某天,月,星期的某天,年;其中年不是必须的,也就是说任何一个表达式最少需要六项!
例:0 0 12 ? * WED 表示每个星期三的12点执行,这里没有“年”这项!

字段名(项)必须 值范围 特殊字符0-59, - * /0-59, - * /0-23, - * /月的某天1-31, - * ? / L W1-12 or JAN-DEC, - * /星期的某天1-7 or SUN-SAT, - * ? / L #empty, 1970-2099, - * /

先看示列:"0 0/30 8-10 5,20 * ?" 表示“每个月的5日和20日的8:00,8:30,9:00,9:30,10:00,10:30”
字符解释:
,:与,表式","两边的值都是需要执行的时间,如上例"5,20",每个月的5日与20日。
-:表示值的范围,如上例"8-10",从8点开始到10结束,包括8点与10点。
*:表式任意可合法的值,如上例"*"是处于月份的字段,所以代表1-12中的任意值,所以上例是指“每个月”。
/:增量,如上例是指从0分开始,每过30分钟取一次值。如果换成"5/8"就是从第5钟开始每过8分钟取一次值:8:05,8:13,8:21,8:29等等
?:不指定值,就是“我也不知道”的意思,只能出现在“月的某天,星期的某天”项中。在什么情况下用呢?如上例如果指定值为星期一,那么可能会出现如4月5日不是星期一,这里就是不对应,有冲突,所以指定为"?",也就是说我也不知道是星期几,只要是5日与20日就行了,至于是星期几我才不管呢!
L:最后的,last的意思,只能出现在“月的某天,星期的某天”项中。表示当前月或当前星期的最后一天,注意的是星期的最后一天为星期六。
W:月中最接近指定日期的普通日(星期一到星期五),只能出现在“月的某天”,如"15W"就是说当前月最接近15日的普通日,如果当月的15是星期三就是星期三,如果当月的15是星期六那么就是昨天也就是星期五,如果当月的15是星期天则为第二天也就是星期一。
#:当前月的第N个星期X日,只能出现在“星期的某天”项中。如"6#3"就是说当前月的第三个星期五,注意"1-7",1=星期天,2=星期一 等等。


Quartz的Cron的格式

  1. Seconds
  2. Minutes
  3. Hours
  4. Day-of-Month
  5. Month
  6. Day-of-Week
  7. Year (optional field)

每天临晨1:30
0 30 1 * * ?


每隔5分钟

"0 0/5 * * * ?"

每隔5分钟后的10秒,即 10:00:10 am, 10:05:10 am, etc.).

"10 0/5 * * * ?"

每周三、周五的10:30, 11:30, 12:30, 和13:30

"0 30 10-13 ? * WED,FRI"

每月5号和20号的8am到10am之间每半个小时(即 8:00, 8:30, 9:00 和 9:30)

"0 0/30 8-9 5,20 * ?"

 

      下面的代码显示了CronTrigger 的一个示例。请注意 SchedulerFactory、Scheduler 和 JobDetail 的实例化,与 SimpleTrigger 示例中的实例化是相同的。在这个示例中,只是修改了触发器。这里指定的 cron 表达式(“0/5 * * * * ?”)安排任务每 5 秒执行一次。

public void task() throws SchedulerException {

    // Initiate a Schedule Factory
    SchedulerFactory schedulerFactory = new StdSchedulerFactory();

    // Retrieve a scheduler from schedule factory
    Scheduler scheduler = schedulerFactory.getScheduler();
   
    // current time
    long ctime = System.currentTimeMillis();
   
    // Initiate JobDetail with job name, job group, and executable job class
    JobDetail jobDetail = new JobDetail("jobDetail2", "jobDetailGroup2", SimpleQuartzJob.class);

    // Initiate CronTrigger with its name and group name
    CronTrigger cronTrigger = new CronTrigger("cronTrigger", "triggerGroup2");

    try {
        // setup CronExpression
        CronExpression cexp = new CronExpression("0/5 * * * * ?");

        // Assign the CronExpression to CronTrigger
        cronTrigger.setCronExpression(cexp);

    } catch (Exception e) {
        e.printStackTrace();
    }

    // schedule a job with JobDetail and Trigger
    scheduler.scheduleJob(jobDetail, cronTrigger);
   
    // start the scheduler
    scheduler.start();
}

 

 

 

 

参考 http://www.ibm.com/developerworks/cn/java/j-quartz/ 《Spring in Action》

 

原创粉丝点击