Quartz核心原理之架构及基本元素介绍 | 京东物流技术团队

1 什么是Quartz

Quartz是一个作业调度框架,它可以与J2EE和J2SE应用相结合,也可以单独使用。它能够创建多个甚至数万个jobs这样复杂的程序,jobs可以做成标准的java组件或EJBS。Quartz很容易上手,创建一个任务仅需实现Job接口,该接口只有一个方法void execute(JobExecutionContext context) throws JobExecutionException;在java实现类添加作业逻辑,当配置好Job实现类并设置调度时间表后,Quartz将会监控任务的剩余时间,当调度程序确定需要通知需要执行该任务的时候,Quartz将会调用Job实现类的execute方法执行任务。

2 系统设计

Quartz框架的原理主要是通过将Job注册到调度器,再通过触发器策略执行Job,系统设计如下:

3 核心元素介绍

Quartz框架的核心是调度器scheduler,核心的组件包括Job(任务)、JobDetail(任务描述)、Trigger(触发器)。调度器负责管理Quartz应用运行时环境。调度器不是靠自己做所有的工作,而是依赖框架内一些非常重要的部件。Quartz不仅仅是线程和线程管理。为确保可伸缩性,Quartz采用了基于多线程的架构。启动时,框架初始化一套worker线程,这套线程被调度器用来执行预定的作业。这就是Quartz怎样能并发运行多个作业的原理。Quartz依赖一套松耦合的线程池管理部件来管理线程环境。

3.1 Job

Job是一个接口,只有一个方法void execute(JobExecutionContext context) throws JobExecutionException。作业类需要实现接口中的execute方法,JobExecutionContext提供了调度的上下文信息,每一次执行Job都会重新创建一个Job对象实例。如下:

1public interface Job { 2 3 /* 4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5 * 6 * Interface. 7 * 8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9 */ 10 11 /** 12 * <p> 13 * Called by the <code>{@link Scheduler}</code> when a <code>{@link Trigger}</code> 14 * fires that is associated with the <code>Job</code>. 15 * </p> 16 * 17 * <p> 18 * The implementation may wish to set a 19 * {@link JobExecutionContext#setResult(Object) result} object on the 20 * {@link JobExecutionContext} before this method exits. The result itself 21 * is meaningless to Quartz, but may be informative to 22 * <code>{@link JobListener}s</code> or 23 * <code>{@link TriggerListener}s</code> that are watching the job's 24 * execution. 25 * </p> 26 * 27 * @throws JobExecutionException 28 * if there is an exception while executing the job. 29 */ 30 void execute(JobExecutionContext context) 31 throws JobExecutionException; 32 33} 34public class ClosePayJob implements Job{ 35public void execute(JobExecutionContext context) throws JobExecutionException{ 36//业务逻辑 37} 38}

3.2 JobDetail

Quartz框架在每次执行Job时,都会重新创建一个Job对象实例,所以它需要Job类的信息以及其他相关信息,以便能够在运行时通过newInstance()的反射机制实例化Job。因此需要通过一个类来描述Job的实现类及其它相关的静态信息,比如Job名字、描述、关联监听器等信息。JobDetail接口包含了能够创建Job类的信息载体,用来保存任务的详细信息。如下代码定义

1public interface JobDetail extends Serializable, Cloneable { 2 3 public JobKey getKey(); 4 5 /** 6 * <p> 7 * Return the description given to the <code>Job</code> instance by its 8 * creator (if any). 9 * </p> 10 * 11 * @return null if no description was set. 12 */ 13 public String getDescription(); 14 15 /** 16 * <p> 17 * Get the instance of <code>Job</code> that will be executed. 18 * </p> 19 */ 20 public Class<? extends Job> getJobClass(); 21 22 /** 23 * <p> 24 * Get the <code>JobDataMap</code> that is associated with the <code>Job</code>. 25 * </p> 26 */ 27 public JobDataMap getJobDataMap(); 28 29 /** 30 * <p> 31 * Whether or not the <code>Job</code> should remain stored after it is 32 * orphaned (no <code>{@link Trigger}s</code> point to it). 33 * </p> 34 * 35 * <p> 36 * If not explicitly set, the default value is <code>false</code>. 37 * </p> 38 * 39 * @return <code>true</code> if the Job should remain persisted after 40 * being orphaned. 41 */ 42 public boolean isDurable(); 43 44 /** 45 * @see PersistJobDataAfterExecution 46 * @return whether the associated Job class carries the {@link PersistJobDataAfterExecution} annotation. 47 */ 48 public boolean isPersistJobDataAfterExecution(); 49 50 /** 51 * @see DisallowConcurrentExecution 52 * @return whether the associated Job class carries the {@link DisallowConcurrentExecution} annotation. 53 */ 54 public boolean isConcurrentExectionDisallowed(); 55 56 /** 57 * <p> 58 * Instructs the <code>Scheduler</code> whether or not the <code>Job</code> 59 * should be re-executed if a 'recovery' or 'fail-over' situation is 60 * encountered. 61 * </p> 62 * 63 * <p> 64 * If not explicitly set, the default value is <code>false</code>. 65 * </p> 66 * 67 * @see JobExecutionContext#isRecovering() 68 */ 69 public boolean requestsRecovery(); 70 71 public Object clone(); 72 73 /** 74 * Get a {@link JobBuilder} that is configured to produce a 75 * <code>JobDetail</code> identical to this one. 76 */ 77 public JobBuilder getJobBuilder(); 78 79}

3.3 Trigger

触发器(org.quartz.Trigger)抽象类的几个主要属性和JobDetail差不多,这里就不说明了,主要注意的是misfireInstruction这个属性,misfireInstruction这个属性的是触发器错失执行(misfire)后的一个错失触发机制标识。当线程池中没有可用的线程执行任务时,就会错过触发时间,Trigger抽象类中默认错失触发机制是常量0(聪明的策略)。派生类有它们自己的错失触发机制。最常用的两种是SimpleTrigger和CronTrigger。

3.3.1 SimpleTrigger

指定从某一个时间开始,以一定的时间间隔(单位是毫秒)执行的任务。

它适合的任务类似于:9:00 开始,每隔1小时,执行一次。

它的属性有:

  • repeatInterval 重复间隔
  • repeatCount 重复次数。实际执行次数是 repeatCount+1。因为在startTime的时候一定会执行一次。** 下面有关repeatCount 属性的都是同理

3.3.2 CronTrigger

适合于更复杂的任务,它支持类型于Linux Cron的语法(并且更强大)。基本上它覆盖了其他Trigger的绝大部分能力—— 当然,也更难理解。

它适合的任务类似于:每天0:00,9:00,18:00各执行一次。

它的属性只有:Cron表达式。

4 总结

本次文章只是对Quartz的架构和基本元素做了简单的介绍,后面我们会深入分析Quartz的核心类。

作者:京东物流 贾永强

来源:京东云开发者社区 自猿其说Tech 转载请注明来源

点赞
收藏

评论区

加载中...

相关推荐

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

mysql中like用法

like的通配符有两种%(百分号):代表零个、一个或者多个字符。\(下划线):代表一个数字或者字符。1\.name以"李"开头wherenamelike'李%'2\.name中包含"云",“云”可以在任何位置wherenamelike'%云%'3\.第二个和第三个字符是0的值wheresalarylike'\00%'4\

Nginx + lua +[memcached,redis]

精品案例1、Nginxluamemcached,redis实现网站灰度发布2、分库分表/基于Leaf组件实现的全球唯一ID(非UUID)3、Redis独立数据监控,实现订单超时操作/MQ死信操作SelectPollEpollReactor模型4、分布式任务调试Quartz应用

mysql中时间比较的实现

MySql中时间比较的实现unix\_timestamp()unix\_timestamp函数可以接受一个参数,也可以不使用参数。它的返回值是一个无符号的整数。不使用参数,它返回自1970年1月1日0时0分0秒到现在所经过的秒数,如果使用参数,参数的类型为时间类型或者时间类型的字符串表示,则是从1970010100:00:0