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实例,如:
- public class ddnjob implements job{
- public void execute(jobexecutioncontext arg0) throws jobexecutionexception {
- perform();
- }
- public void perform(){ //执行报表统计入口函数
- //业务逻辑
- system.out.println("自动ddn预授权开始执行-------------执行时间:"+new date());
- }
- }
注:ddnjob类为需要定时执行的类,execute为定时执行的方法。一个定时任务对应一个job实现类。
2、jobdetail
quartz在每次执行job时,都重新创建一个job实例,所以它不直接接受一个job的实例,相反它接收一个job实现类,以便运行时通过newinstance()的反射机制实例化job。因此需要通过一个类来描述job的实现类及其它相关的静态信息,如job名字、描述、关联监听器等信息,jobdetail承担了这一角色。jobdetail 用来保存我们作业的详细信息。一个jobdetail可以有多个trigger,但是一个trigger只能对应一个jobdetail,
示例:
- jobdetail jobdetail = new jobdetail("myjob","mygroup",ddnjob.class)
- 说明:
- myjob:job 名
- mygroup:job 组(为'null'时,使用缺省的组sched.default_group)
- ddnjob.class:要被执行的java类。
运用spring集成的methodinvokingjobdetailfactorybean时spring能自动生成符合quartz要去的jobdetail。
spring中applicationcontext.xml配置如下:
- <!-- detail任务描述 -->
- <bean name="ddndetail"
- class="com.mangocity.mpm.common.autoddn.methodinvokingjobdetailfactorybean">
- <property name="targetobject" value="ddnjob" />
- <property name="concurrent" value="false"/>(并发执行)
- <property name="shouldrecover" value="true"/>
- </bean>
3、trigger
trigger是一个类,描述触发job执行的时间触发规则。主要有simpletrigger和 crontrigger这两个子类。当仅需触发一次或者以固定时间间隔周期执行,simpletrigger是最适合的选择;而crontrigger则 可以通过cron表达式定义出各种复杂时间规则的调度方案:如每早晨9:00执行,周一、周三、周五下午5:00执行等;spring中applicationcontext.xml配置如下:
simpletrigger使用示例:
- <bean id="ddnsimpletrigger" class="org.springframework.scheduling.quartz.simpletriggerbean">
- <property name="jobdetail" ref="ddndetail"/>
- <property name="startdelay" value="1"/>
- <property name="repeatcount" value="100"/>
- <property name="repeatinterval" value="1000"/>
- </bean>
crontrigger使用示例:
- // 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();
- }
通过spring配置,jobdetail为配置的job描述,cronexpression为job的运行规则,具体见附录部分内容。
- <bean id="ddncrontrigger" class="org.springframework.scheduling.quartz.crontriggerbean">
- <property name="jobdetail" ref="ddndetail"/>
- <property name="cronexpression" value="0/5 * * ? * * *"/>
- </bean>
4、scheduler
scheduler负责管理quartz的运行环境,quartz它是基于多线程架构的,它启动的时候会初始化一套线程,这套线程会用来执行一些预置的作业。trigger和jobdetail可以注册到scheduler中;scheduler可以将trigger绑定到某一jobdetail中,这样当trigger触发时,对应的job就被执行。 scheduler拥有一个schedulercontext,它类似于servletcontext,保存着scheduler上下文信息,job和trigger都可以访问schedulercontext内的信息。scheduler使用一个线程池作为任务运行的基础设施,任务通过共享线程池中的线程提高运行效率。 应用示例:
- schedulerfactory schedulerfactory = new stdschedulerfactory();
- // retrieve a scheduler from schedule factory
- scheduler scheduler = schedulerfactory.getscheduler();
- …
- // schedule a job with jobdetail and trigger
- scheduler.schedulejob(jobdetail, simpletrigger);
- // start the scheduler
- scheduler.start();
spring中applicationcontext.xml配置:
- <!-- 调度器 -->
- <bean class="org.springframework.scheduling.quartz.schedulerfactorybean">
- <property name="datasource">
- <ref bean="datasource"/>
- </property>
- <property name="triggers">
- <list>
- <!-- 触发器列表 -->
- <!-- <ref bean="ddncrontrigger" /> -->
- <ref bean="ddnsimpletrigger" />
- </list>
- </property>
- <property name="configlocation" value="classpath:quartz.properties" />
- </bean>
其中,datasource为数据源配置,triggers为触发器列表配置,可以同时包含多个trigger,configlocation为quartz配置文件quartz.properties加载路径。
四、总结:
我们不只有一种两种方法来实现我们的定时任务,就我知道的出了我们的quartz框架之外,我们spring也自己封装有自己的定时器,再加上各种开源的插件。那我工作的公司来说,我们用windows服务来完成这个定时任务,万变不离其宗,理解了他们的原理以及精髓,我们就可以去创新,去写出符合自己要求的工具了!