Quartz实现任务调度

时间:2018-11-07
本文章向大家介绍Quartz实现任务调度,需要的朋友可以参考一下

一、Quartz概述:

       Quartz是一个完全由Java编写的开源任务调度的框架,通过触发器设置作业定时运行规则,控制作业的运行时间。其中quartz集群通过故障切换和负载平衡的功能,能给调度器带来高可用性和伸缩性。主要用来执行定时任务,如:定时发送信息、定时生成报表等等。

二、相关术语:

       调度器Scheduler :Quartz框架的核心是调度器。调度器负责管理Quartz应用运行时环境。调度器不是靠自己做所有的工作,而是依赖框架内一些非常重要的部件。Quartz不仅仅是线程和线程池管理。为确保可伸缩性,Quartz采用了基于多线程的架构。启动时,框架初始化一套worker线程,这套线程被调度器用来执行预定的作业。这就是Quartz怎样能并发运行多个作业的原理。Quartz依赖一套松耦合的线程池管理部件来管理线程环境。
      任务JobDetail:这个很简单,就是我们自己编写的业务逻辑,交给quartz帮我们执行 。
      触发器Trigger :简单的讲就是调度作业,什么时候开始执行,什么时候结束执行。

三、Quartz的体系结构简介:

       Quartz框架主要核心组件包括调度器、触发器、作业。调度器作为作业的总指挥,触发器作为作业的操作者,作业为应用的功能模块。其关系如下图所示:

 Job为作业的接口,为任务调度的对象;JobDetail用来描述Job的实现类及其它相关的静态信息;Trigger做为作业的定时管理工具,一个Trigger只能对应一个作业实例,而一个作业实例可对应多个触发器;Scheduler做为定时任务容器,是quartz最上层的东西,它提携了所有触发器和作业,使它们协调工作,每个Scheduler都存有JobDetail和Trigger的注册,一个Scheduler中可以注册多个JobDetail和多个Trigger。

1、Job

      Job是一个接口,只有一个方法void execute(JobExecutionContext context),被调度的作业(类)需实现该接口中execute()方法,JobExecutionContext类提供了调度上下文的各种信息。每次执行该Job均重新创建一个Job实例,如:

  1. public class DDNJob implements Job{  
  2.   
  3.     public void execute(JobExecutionContext arg0) throws JobExecutionException {  
  4.         perform();  
  5.     }  
  6.       
  7.     public void perform(){ //执行报表统计入口函数    
  8.         //业务逻辑    
  9.                 System.out.println("自动DDN预授权开始执行-------------执行时间:"+new Date());    
  10.         }    
  11. }  

注:DDNJob类为需要定时执行的类,execute为定时执行的方法。一个定时任务对应一个Job实现类。

2、JobDetail

Quartz在每次执行Job时,都重新创建一个Job实例,所以它不直接接受一个Job的实例,相反它接收一个Job实现类,以便运行时通过newInstance()的反射机制实例化Job。因此需要通过一个类来描述Job的实现类及其它相关的静态信息,如Job名字、描述、关联监听器等信息,JobDetail承担了这一角色。JobDetail 用来保存我们作业的详细信息。一个JobDetail可以有多个Trigger,但是一个Trigger只能对应一个JobDetail,

示例:

  1.  JobDetail jobDetail = new JobDetail("myJob","myGroup",DDNJob.class)   
  2.  说明:    
  3.  myJob:job 名     
  4.   myGroup:job 组(为'null'时,使用缺省的组sched.DEFAULT_GROUP)     
  5.  DDNJob.class:要被执行的Java类。 

运用spring集成的MethodInvokingJobDetailFactoryBean时spring能自动生成符合quartz要去的JobDetail。
Spring中applicationContext.xml配置如下:

  1. <!-- detail任务描述 -->   
  2.     <bean name="DDNDetail"    
  3.         class="com.mangocity.mpm.common.autoDDN.MethodInvokingJobDetailFactoryBean">    
  4.         <property name="targetObject" value="DDNJob" />  
  5.         <property name="concurrent" value="false"/>(并发执行)  
  6.         <property name="shouldRecover" value="true"/>    
  7.     </bean>    

3、Trigger

Trigger是一个类,描述触发Job执行的时间触发规则。主要有SimpleTrigger和 CronTrigger这两个子类。当仅需触发一次或者以固定时间间隔周期执行,SimpleTrigger是最适合的选择;而CronTrigger则 可以通过Cron表达式定义出各种复杂时间规则的调度方案:如每早晨9:00执行,周一、周三、周五下午5:00执行等;Spring中applicationContext.xml配置如下:

SimpleTrigger使用示例

  1. <bean id="DDNSimpletrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">  
  2.         <property name="jobDetail" ref="DDNDetail"/>  
  3.         <property name="startDelay" value="1"/>  
  4.         <property name="repeatCount" value="100"/>   
  5.         <property name="repeatInterval" value="1000"/>  
  6. </bean>  

CronTrigger使用示例

  1. // Initiate CronTrigger with its name and group name  
  2. CronTrigger cronTrigger = new CronTrigger("cronTrigger","triggerGroup2");  
  3. try {  
  4.     // setup CronExpression  
  5.      CronExpression cexp = new CronExpression("0/5 * * * * ?");  
  6. // Assign the CronExpression to CronTrigger  
  7.      cronTrigger.setCronExpression(cexp);  
  8. } catch (Exception e) {  
  9.        e.printStackTrace();  
  10. }  

通过Spring配置,jobDetail为配置的Job描述,cronExpression为Job的运行规则,具体见附录部分内容。

  1. <bean id="DDNCrontrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">  
  2.         <property name="jobDetail" ref="DDNDetail"/>  
  3.         <property name="cronExpression" value="0/5 * * ? * * *"/>  
  4. </bean>      

4、Scheduler

        Scheduler负责管理Quartz的运行环境,Quartz它是基于多线程架构的,它启动的时候会初始化一套线程,这套线程会用来执行一些预置的作业。Trigger和JobDetail可以注册到Scheduler中;Scheduler可以将Trigger绑定到某一JobDetail中,这样当Trigger触发时,对应的Job就被执行。         Scheduler拥有一个SchedulerContext,它类似于ServletContext,保存着Scheduler上下文信息,Job和Trigger都可以访问SchedulerContext内的信息。Scheduler使用一个线程池作为任务运行的基础设施,任务通过共享线程池中的线程提高运行效率。 应用示例:   

  1. SchedulerFactory schedulerFactory = new StdSchedulerFactory();  
  2.     // Retrieve a scheduler from schedule factory  
  3.     Scheduler scheduler = schedulerFactory.getScheduler();  
  4.      …  
  5.     // schedule a job with JobDetail and Trigger  
  6.      scheduler.scheduleJob(jobDetail, simpleTrigger);  
  7.     // start the scheduler  
  8.     scheduler.start();  

Spring中applicationContext.xml配置:

  1. <!-- 调度器  -->    
  2.     <bean  class="org.springframework.scheduling.quartz.SchedulerFactoryBean">   
  3.         <property name="dataSource">  
  4.             <ref bean="dataSource"/>  
  5.         </property>   
  6.         <property name="triggers">    
  7.             <list>    
  8.                 <!--  触发器列表 -->    
  9.                 <!-- <ref bean="DDNcronTrigger" />  -->  
  10. <ref bean="DDNSimpletrigger" />  
  11.             </list>    
  12.         </property>   
  13.         <property name="configLocation" value="classpath:quartz.properties" />  
  14.     </bean>  

其中,dataSource为数据源配置,triggers为触发器列表配置,可以同时包含多个trigger,configLocation为quartz配置文件quartz.properties加载路径。

四、总结:

       我们不只有一种两种方法来实现我们的定时任务,就我知道的出了我们的quartz框架之外,我们spring也自己封装有自己的定时器,再加上各种开源的插件。那我工作的公司来说,我们用windows服务来完成这个定时任务,万变不离其宗,理解了他们的原理以及精髓,我们就可以去创新,去写出符合自己要求的工具了!