Quartz:任务调度实现原理

简介: Quartz:任务调度实现原理

什么是Quartz

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

Quartz允许开发人员根据时间间隔来调度作业。

它实现了作业和触发器的多对多的关系,还能把多个作业与不同的触发器关联。简单地创建一个org.quarz.Job接口的Java类。


Quartz的特点

作为一个优秀的开源调度框架,Quartz 具有以下特点:

① 强大的调度功能,例如支持丰富多样的调度方法,可以满足各种常规及特殊需求;

② 灵活的应用方式,例如支持任务和调度的多种组合方式,支持调度数据的多种存储方式;

分布式和集群能力,Terracotta 收购后在原来功能基础上作了进一步提升。

④ Quartz 很容易与 Spring 集成实现灵活可配置的调度功能。

 

Quartz专用词汇说明

下面是本文中用到的一些专用词汇,在此声明:

scheduler任务调度器

trigger触发器,用于定义任务调度时间规则

job任务,即被调度的任务

misfire错过的,指本来应该被执行但实际没有被执行的任务调度

 

Quartz任务调度基本实现原理:

Quartz任务调度的核心元素为:Scheduler——任务调度器、Trigger——触发器、Job——任务。

其中trigger和job是任务调度的元数据,scheduler是实际执行调度的控制器。


Trigger

  • 是用于定义调度时间的元素,即按照什么时间规则去执行任务。
  • Quartz中主要提供了四种类型的trigger:SimpleTrigger,CronTirgger,DateIntervalTrigger,和NthIncludedDayTrigger。
  • 这四种trigger可以满足企业应用中的绝大部分需求。


Job

  • 用于表示被调度的任务。
  • 主要有两种类型的job:无状态的(stateless)和有状态的(stateful)
  • 对于同一个trigger来说,有状态的job不能被并行执行,只有上一次触发的任务被执行完之后,才能触发下一次执行。
  • Job主要有两种属性:volatility和durability,其中volatility表示任务是否被持久化到数据库存储,而durability表示在没有trigger关联的时候任务是否被保留。两者都是在值为true的时候任务被持久化或保留。
  • 一个job可以被多个trigger关联,但是一个trigger只能关联一个job


Scheduler

  • scheduler由scheduler工厂创建:DirectSchedulerFactory或者StdSchedulerFactory。
  • StdSchedulerFactory使用较多,因为DirectSchedulerFactory使用起来不够方便,需要作许多详细的手工编码设置。
  • Scheduler主要有三种:RemoteMBeanScheduler,RemoteScheduler和StdScheduler。StdScheduler 为最常用。


Quartz 线程视图

  在Quartz中,有两类线程,Scheduler调度线程和任务执行线程,其中任务执行线程通常使用一个线程池维护一组线程。

 

Scheduler调度线程主要有两个:执行常规调度的线程,和执行misfiredtrigger的线程。

常规调度线程:轮询存储的所有trigger,如果有需要触发的trigger,即到达了下一次触发的时间,则从任务执行线程池获取一个空闲线程,执行与该trigger关联的任务。

Misfire线程:是扫描所有的trigger,查看是否有misfiredtrigger,如果有的话根据misfire的策略分别处理(fire now OR wait for the next fire)。

 

Quartz Job数据存储

Quartz中的trigger和job需要存储下来才能被使用。

Quartz中有两种存储方式:RAMJobStore,JobStoreSupport。

RAMJobStore是将trigger和job存储在内存中,而JobStoreSupport是基于jdbc将trigger和job存储到数据库中。

RAMJobStore的存取速度非常快,但是由于其在系统被停止后所有的数据都会丢失,所以在集群应用中,必须使用JobStoreSupport。


任务调度器调度的时序:

 

在这里将几个重要的类调用的过程以序列图的形式展现出来,上半部分展现的是启动过程,下半部分展现的是任务调度的过程。

步骤1.用户首先需要生成一个调度器工厂SchedulerFactory,可以用下面的方式实现自己的定制化:

Properties properties=new Properties();    
properties.put("org.quartz.threadPool.class","org.quartz.simpl.SimpleThreadPool");
properties.put("org.quartz.threadPool.threadCount","10");
SchedulerFactory sf=new StdSchedulerFactory(properties);

步骤2.然后通过getScheduler()方法从调度器工厂里得到调度器实例,首先查找有没有这样的调度器,没有的话,就生成一个,有的话直接返回。所以得到的一般是单例,即默认的调度器。

步骤3.Scheduler有一个QuartzSchedulerThread(Thread的子类)属性,在scheduler实例化的时候,实例化了一个对象,并用ThreadExecutor启动该线程对象。该线程就是调度线程,主要任务就是不停的从JobStore中获取即将被触发的触发器(默认30s调度一次)。在这个时候调度线程虽然启动,但是处于pause状态。

步骤4.接下来是任务调度的部分:

Scheduler scheduler=sf.getScheduler();
scheduler.addJobListener(new TaskListener());
scheduler.scheduleJob(jobDetail, simpleTrigger);
scheduler.start();

client通过scheduleJob()方法将任务和触发器存储在JobStore中,通过start()方法将QuartzSchedulerThread的pause状态设为false,通知调度线程执行任务,此后调度线程不停的从JobStore中去取即将触发的任务。

 

任务执行的时序:

 

上半部分展现的是任务执行之前准备工作的时序,下半部分展现的是任务执行的时序。

步骤1.调度线程首先去线程池中获取可用的线程,如果没有的话,就阻塞。

步骤2.从JobStore(从存储介质中获取触发器,存储介质可以是内存也可以是数据库)获取(接下来30s内的)触发器,然后等待该触发器触发。

步骤3.调度线程创建一个JobRunShell(就是一个Runnable),然后从线程池中调用线程执行该任务。

接下来就是任务执行的时序:

步骤4.获取trigger、JobDetail以及生成Job实例,然后执行job的execute接口函数。

 

持久化的任务的执行时序:

 

以上就是Quartz的基本工作流程。

参考来源:https://www.cnblogs.com/zhangchengzhangtuo/p/5705672.html


目录
相关文章
|
存储 SQL Java
分布式任务调度框架(一):Quartz
Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,是完全由java开发的一个开源的任务日程管理系统,“任务进度管理器”就是一个在预先确定(被纳入日程)的时间到达时,负责执行(或者通知)其他软件组件的系统。其功能类似于java.util.Timer。但是相较于Timer, Quartz增加了很多功能,作为一个优秀的开源调度框架
714 0
分布式任务调度框架(一):Quartz
|
存储 开发框架 Java
分布式定时任务框架Quartz总结和实践(1)
Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。Jobs可以做成标准的Java组件或 EJBs。
202 0
|
存储 Oracle Java
如何使用Quartz框架来实现任务调度?
如何使用Quartz框架来实现任务调度?
114 0
|
开发框架 Java Linux
Quartz-任务调度概述及Quartz(2.2.X)快速入门
Quartz-任务调度概述及Quartz(2.2.X)快速入门
210 0
|
存储 运维 Java
分布式定时任务-QuartzJava编程
分布式定时任务-QuartzJava编程
分布式定时任务-QuartzJava编程
|
存储 运维 Java
分布式定时任务-Quartz
分布式定时任务-Quartz
分布式定时任务-Quartz
Quartz3定时任务学习之异步调度器
Quartz3定时任务学习之异步调度器 Quartz3与Quartz2的主要区别有两点: 1,Quartz3将它的资源类库拆的更细了,比如,想使用Quartz3开发,最少要引用Quartz,Quartz.Jobs,Quartz.Plugins这三个类库。 2,Quartz3整体上使用的是异步创建实例,所以我们使用时就必须要async,await的语法。 下面我们用Quartz3来做一个任务调度。
Quartz3定时任务学习之异步调度器
|
监控 关系型数据库 调度
Spring整合Quartz分布式调度
为了保证应用的高可用和高并发性,一般都会部署多个节点;对于定时任务,如果每个节点都执行自己的定时任务,一方面耗费了系统资源,另一方面有些任务多次执行,可能引发应用逻辑问题,所以需要一个分布式的调度系统,来协调每个节点执行定时任务。
8549 0