Timer, Quartz 和 Spring 实现作业调度

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

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

二、Quartz
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

       OpenSymphony Quartz提供了一个比较完美的任务调度解决方案。

       Quartz 是个开源的作业调度框架,为在 Java 应用程序中进行作业调度提供了简单却强大的机制。

       Quartz中有两个基本概念:作业和触发器。作业是能够调度的可执行任务,触发器提供了对作业的调度。


1、作业

实现 org.quartz.job 接口,实现接口方法 public void execute(JobExecutionContext context) throws JobExecutionException,在这个方法实现具体的作业任务。

      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 触发器利用一系列特殊字符,如下所示:

  • 反斜线(/)字符表示增量值。例如,在秒字段中“5/15”代表从第 5 秒开始,每 15 秒一次。
    <!--[endif]-->
  • 问号(?)字符和字母 L 字符只有在月内日期和周内日期字段中可用。问号表示这个字段不包含具体值。所以,如果指定月内日期,可以在周内日期字段中插入“?”,表示周内日期值无关紧要。字母 L 字符是 last 的缩写。放在月内日期字段中,表示安排在当月最后一天执行。在周内日期字段中,如果“L”单独存在,就等于“7”,否则代表当月内周内日期的最后一个实例。所以“0L”表示安排在当月的最后一个星期日执行。
    <!--[endif]-->
  • 在月内日期字段中的字母(W)字符把执行安排在最靠近指定值的工作日。把“1W”放在月内日期字段中,表示把执行安排在当月的第一个工作日内。
    <!--[endif]-->
  • 井号(#)字符为给定月份指定具体的工作日实例。把“MON#2”放在周内日期字段中,表示把任务安排在当月的第二个星期一。
    <!--[endif]-->
  • 星号(*)字符是通配字符,表示该字段可以接受任何可能的值。

所有这些定义看起来可能有些吓人,但是只要几分钟练习之后,cron 表达式就会显得十分简单。

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

 

三、Spring + Quartz

springJavaTimer类和Quartz都提供了一个抽象层,使用我们可以更方便地使用它们。

1springTimer的集成

首先是一个定时器任务

public class EmailReportTask extends TimerTask {

    public EmailReportTask() {

   

    }

 

    public void run() {

        courseService.sendCourseEnrollmentReport();

    }

 

    private CourseService courseService;

    public void setCourseService(CourseService courseService) {

        this.courseService = courseService;

    }

}

spring配置文件中配置EmailReportTask

 

<bean id="reportTimerTask"    

           class="com.springinaction.training.schedule.EmailReportTask">   

       <property name="courseService">          

              <ref bean="courseService"/>       

       </property>    

</bean>   

 

调度定时器任务

       <bean id="scheduledReportTask"    

               class="org.springframework.scheduling.timer.ScheduledTimerTask">    

           <property name="timerTask">      

                     <ref bean="reportTimerTask"/>    

           </property>

           <property name="period">      

                     <value>86400000</value>    

           </property>

              <property name="delay">      

                     <value>32000</value>      

           </property>    

       </bean>   

 

启动定时器

       <bean class="org.springframework.scheduling.timer.TimerFactoryBean"> 

           <property name="scheduledTimerTasks"> 

               <list>    

                   <ref bean="scheduledReportTask"/>                         

               </list>   

           </property> 

       </bean>    

      

2springQuartz的集成

 

创建一个工作

       public class EmailReportJob extends QuartzJobBean { 

            public EmailReportJob() {  

        

           }  

           protected void executeInternal(JobExecutionContext context)  throws JobExecutionException {  

               courseService.sendCourseEnrollmentReport();  

           }  

        

           private CourseService courseService;  

           public void setCourseService(CourseService courseService) {  

               this.courseService = courseService;  

           }  

       } 

      

spring配置文件的配置EmailReportJob

       <bean id="reportJob" 

             class="org.springframework.scheduling.quartz.JobDetailBean"> 

           <property name="jobClass"> 

               <value>com.springinaction.training.schedule.EmailReportJob</value> 

           </property> 

           <property name="jobDataAsMap"> 

               <map> 

                   <entry key="courseService"> 

                       <ref bean="courseService" /> 

                   </entry> 

               </map> 

           </property> 

       </bean> 

 

调度工作

       quartz对应,Spirng提供了两个触发器SimpleTriggerBeanCronTriggerBean

    使用SimpleTriggerBean触发器

 

       <bean id="simpleReportTrigger" 

                     class="org.springframework.scheduling.quartz.SimpleTriggerBean"> 

           <property name="jobDetail"> 

               <ref bean="reportJob"/> 

           </property> 

           <property name="startDelay"> 

               <value>3600000</value> 

           </property> 

           <property name="repeatInterval"> 

               <value>86400000</value> 

           </property> 

       </bean> 

 

使用CronTriggerBean触发器

       <bean id="cronReportTrigger" 

               class="org.springframework.scheduling.quartz.CronTriggerBean"> 

           <property name="jobDetail"> 

               <ref bean="reportJob" /> 

           </property> 

           <property name="cronExpression"> 

               <value>0 * * * * ?</value> 

           </property> 

       </bean> 

统会在每分钟的0秒执行调度任务。

 

参考

 http://www.ibm.com/developerworks/cn/java/j-quartz/

Spring in Action

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值