前序:
     我们已经在前面的内容能里看到了,我们用 Scheduler 来管理我们的 Job;创建并关联触发器以使 Job 能被触发执行;以及如可选择 calendar 为给定的时程安排提供更多的灵活性。

1.Quartz 调度器的介绍

     调度器(Scheduler) 是Quartz 框架的心脏,Scheduler也是 Quartz 的主要 API。对于
Quartz 用户来说,多数时候与框架的交互是发生于 Scheduler  之上的。客服端与 Scheduler 交互是通过
org.quartz.Scheduler接口的。从Quartz内部来说,我们可以从前面看出,它是任务执行的一个平台,如果光有任务没有调度器的存
在,众多任务也不会实现为多任务的批处理;

      我们访问Quartz的时候,其实Scheduler并不是真正的处理类,这个Scheduler
的实现,在这种情况下,是一个代理,对其中方法调用会传递到 QuartzScheduler
实例上。QuartzScheduler对于客户端是不可见的,并且也不存在与此实例的直接交互;

       QuartzScheduler 处在框架根的位置,它是一个引擎驱动着整个框架。并非所有的功能都直接内建到
QuartzScheduler,然而,框架为灵活性和可配置性考虑而设计,所以许多重要的功能由分离的组件和子框架实现。这就意味着 Quartz
用户可以用自己某个关键特征实现来替换原有默认实现。即使 QuartzScheduler 代理了它的一些职责,但它仍然掌控着整个作业调度流程

2.Quartz Scheduler 的类层次

Scheduler为一个接口,客户端会同两种类型的 Scheduler 交互,它们都实现了 

org.quartz.Scheduler 接口。

               Scheduler

StdScheduler        RemoteScheduler;

3.Quartz SchedulerFactory 调度器工厂类

  Quartz SchedulerFactory 为一个创建任务调度器的工厂类;

他的工厂方法来确保了构造出 Sheduler 实例并正确的得到初始化,当 Scheduler
实例被创建之后,就会存到一个仓库中(org.quartz.impl.SchedulerRepository),这个仓库还提供了通过一个
class loader 查询实例的机制。要使用 Scheduler
实例,客户端必须从工厂(和随同的仓库中)使用不同方法调用来获取到它们。换句话说,要通过工厂创建一个 Scheduler
实例并获取到它需要经由两次方法调用。有一些方便的方法封装了那两个方法,你将很快能看到。

一个是create动作,一个是get动作;

SchedulerFactory也只是一个接口,他有具体两个实现类分别为:

 

  a.org.quartz.impl.DirectoSchedulerFactory

  b.org.quartz.impl.StdSchedulerFactory

4.DirectSchedulerFactory

DirectSchedulerFactory 是为那些想绝对控制 Scheduler 实例是如何生产出的人所

设计的。下面的代码显示了最简单的方式去使用 DirectSchedulerFactory

来创建一个 Scheduler 实例。

  1. /**
  2. * 测试DirectSchedulerFactory的功能
  3. * @author liuwei
  4. *
  5. */
  6. public class DirectSchedulerFactoryTest {
  7. static Log logger = LogFactory.getLog
  8. (DirectSchedulerFactoryTest.class);
  9. /**
  10. * 测试DirectSchedulerFactory的功能
  11. * @param args
  12. */
  13. public static void main(String[] args) {
  14. DirectSchedulerFactoryTest example=new DirectSchedulerFactoryTest();
  15. example.startScheduler();
  16. }
  17. /**
  18. *根据DirectSchedulerFactory创建一个任务调度器实例
  19. */
  20. public void startScheduler() {
  21. /*静态方法 getInstance() 获取到工厂的实例*/
  22. DirectSchedulerFactory factory=DirectSchedulerFactory.getInstance()
  23. try {
  24. /*
  25. * createVolatileScheduler() 方法创建 Scheduler 实例的。
  26. * 方法 createVolatileScheduler() 带有单个参数:要创建的线程数量
  27. */
  28. factory.createVolatileScheduler(10);
  29. //获取一个任务调度器实例通过工厂类
  30. Scheduler scheduler = factory.getScheduler();
  31. //启动该任务调度器,并执行上面注册的作业任务
  32. logger.info("Scheduler starting up...");
  33. //启动任务调度器;
  34. scheduler.start();
  35. } catch (SchedulerException ex) {
  36. logger.error(ex);
  37. }
  38. }
  39. }

注意:

在调用 getScheduler() 方法之前调用其中的一个 createXXX 方法 ;

方法 createVolatileScheduler() 方法不会返回 scheduler 的实例。createXXX()
方法是告诉工厂如何配置要创建的 Scheduler 实例。你必须调用方法 getScheduler() 获取到在工厂上执行方法
createXXX() 产生的实例。实际上,在调用 getScheduler() 方法之前,你必须调用其中一个 createXXX()
方法;否则,你将有收到一个 SchedulerException 错误,因为根本没有 Scheduler 实例存在。

我们上面获取的为Scheduler接口的实现StdScheduler的实例,那么我们如何根据factory来创建一个RemoteScheduler呢?

  1. public void createRemoteScheduler(String rmiHost, int rmiPort)
  2. throws SchedulerException;
  3. protected void createRemoteScheduler(String schedulerName,
  4. String schedulerInstanceId, String rmiHost, int rmiPort)
  5. throws SchedulerException;

对于标准任务调度器的创建,通过工厂类的createVolatileScheduler()方法是不够的

  1. public void createScheduler(ThreadPool threadPool, JobStore jobStore)throws SchedulerException;
  2. public void createScheduler(String schedulerName,
  3. String schedulerInstanceId, ThreadPool threadPool, JobStore jobStore) throws SchedulerException;
  4. public void createScheduler(String schedulerName,String
  5. schedulerInstanceId, ThreadPool threadPool,JobStore jobStore, String rmiRegistryHost, int rmiRegistryPort,long idleWaitTime, long dbFailureRetryInterval)throws SchedulerException;

5.StdSchedulerFactory

   我们都可以看出来,上面DirectSechdulerFactory是通过create的方式来初始化任务调度器的相关信息,我们可否通过文件配置的形式来实现我们的

任务调度器信息的初始化呢?StdSchedulerFactory,另一个 SchedulerFactory
版本,它依赖于一系列的属性来配置 Scheduler,而不是通过 createXXX() 方法参数来传递配置参数。这样也避免了在代码中对
Scheduler 的配置选项的硬编码。

    它提供了三种方式来实现通知工厂类创建任务调度器实例的属性;

    我们可以通过以下三种途径向工厂提供那些属性:

·通过 java.util.Properties 实例提供

·通过外部属性文件提供

·通过含用属性文件内容的 java.io.InputStream 实例提供

下面我们将一个个的来实现上面的三种方式

a.通过java.util.Properties 实例创建 StdSchedulerFactory

  1. /**
  2. * 通过java.util.Properties类来实现创建Secheduler
  3. * @author liuwei
  4. */
  5. public class PropertiesStdSechedulerFactory {
  6. static Log logger = LogFactory.getLog
  7. (PropertiesStdSechedulerFactory.class);
  8. /**
  9. *调度器的执行模拟
  10. */
  11. public static void main(String[] args) {
  12. PropertiesStdSechedulerFactory example = new
  13. PropertiesStdSechedulerFactory();
  14. example.startScheduler();
  15. }
  16. /**
  17. * 获取任务调度器方法
  18. */
  19. public void startScheduler() {
  20. /*创建一个StdSchedulerFactory实例*/
  21. StdSchedulerFactory factory = new StdSchedulerFactory();
  22. /*创建一个Properties类,来实现对工厂类的属性初始化*/
  23. Properties props = new Properties();
  24. /*
  25. * 初始化两个属性
  26. * StdSchedulerFactory.PROP_THREAD_POOL_CLASS --
  27. *  org.quartz.simpl.SimpleThreadPool
  28. * org.quartz.threadPool.threadCount          --10
  29. */
  30. props.put(StdSchedulerFactory.PROP_THREAD_POOL_CLASS,"org.quartz.simpl.SimpleThreadPool");
  31. props.put("org.quartz.threadPool.threadCount", "10");
  32. try {
  33. /*根据属性信息初始化工厂类*/
  34. factory.initialize(props);
  35. //获取一个任务调度器实例通过工厂类
  36. Scheduler scheduler = factory.getScheduler();
  37. //启动该任务调度器,并执行上面注册的作业任务
  38. logger.info("Scheduler starting up...");
  39. scheduler.start();
  40. } catch (SchedulerException ex) {
  41. logger.error(ex);
  42. }
  43. }
  44. }

b.外部文件实现属性初始化

   工厂也能通过传入一个外部文件名而被初始化,在这个外部文件中包含了这些配置项。应使用 initialize() 的替代方法形式如下:

  1. public void initialize(String filename) throws SchedulerException;

Java 属性文件

我们这里使用述语“属性文件”,对于 Java 传统来说就是:在一个外部文件中指定一系列的 key=value  对,并且每个 key=value 对独占一行。

要使文件和属性能被成功加载的话,这个文件必须对于 classloader 是可见的。也就是说它必须在你的应用程序的 classpath 中

c.文件输入流的形式

    假如你用的是 java.io.InputStream 去加载文件,你可以使用另一个 initialize() 的替代方法如下:

  1. public void initialize(InputStream propertiesStream) throws SchedulerException;

注意,假使我们对于stdSechedulerFactory的initialize没有指定属性,那么 StdSchedulerFactory 会试图从名为 quartz.properties 的文件中加载它们;

对于默认读取properties的过程,分析如下:

·使用默认的 quartz.properties 文件创建 Scheduler

假如你使用无参的 initialize() 方法,StdSchedulerFactory 会执行以下几个步骤去尝试为工厂加载属性:

1).  检查 System.getProperty("org.quartz.properties") 中是否设置了别的文件名

2).  否则,使用 quartz.properties 作为要加载的文件名

3).  试图从当前工作目录中加载这个文件

4).  试图从系统 classpath 下加载这个文件

在 Quartz Jar 包中的默认 quartz.properties 文件

上面第4步总是能成功的,因为在 Quartz Jar 包中有一个默认的 quartz.properties 文件。假如你想使用另一个替代文件,你必须自己创建一个并确保它在 classpath 上。

StdSchedulerFactory 直接提供了一个方便的静态方法 getDefaultScheduler(),它也就是调用了前面的三个initialize方法中的一个;

如果一次initialize方法都没有别调用,则它将调用一个默认的无参initialize方法!也就是说,它将默认将quartz.properties文件做为默认的初始化信息;

任务调度器的作用

Scheduler 的 API 可以分组成以下三个类别:

    ·管理 Scheduler

·管理 Job

·管理 Trigger 和 Calendar

企业级任务调度框架Quartz(6) 任务调度器(Scheduler)的更多相关文章

  1. 企业级任务调度框架Quartz(1) --企业应用中的任务调度介绍

    由于目前的工作内容为建行CLPM批处理业务的设计工作,所以很好的理解批处理所用的任务调度框架Quartz势在必行:为了能够更好的去服务于工作,也 为了提升自己,所以我学习了Quartz Job Sch ...

  2. Java任务调度框架Quartz入门

    Quartz[kwɔːts]:石英,其框架和名字一样简单朴素又不失魅力,在Java程序界,Quartz大名鼎鼎,很多Java应用几乎都集成或构建了一个定时任务调度系统,Quartz是一个定时任务调度框 ...

  3. 通过源码分析Java开源任务调度框架Quartz的主要流程

    通过源码分析Java开源任务调度框架Quartz的主要流程 从使用效果.调用链路跟踪.E-R图.循环调度逻辑几个方面分析Quartz. github项目地址: https://github.com/t ...

  4. SpringBoot整合任务调度框架Quartz及持久化配置

    目录 本篇要点 SpringBoot与Quartz单机版快速整合 引入依赖 创建Job 调度器Scheduler绑定 自动配置,这里演示SimpleScheduleBuilder 手动配置,这里演示C ...

  5. [源码分析] 定时任务调度框架 Quartz 之 故障切换

    [源码分析] 定时任务调度框架 Quartz 之 故障切换 目录 [源码分析] 定时任务调度框架 Quartz 之 故障切换 0x00 摘要 0x01 基础概念 1.1 分布式 1.1.1 功能方面 ...

  6. 企业级任务调度框架Quartz(4) 多个job实例注册到任务调度器上

    前序:     在第一个例子我看到了自定义的作业类在任务调度器上注册后,则通过任务调度器来实现启动:下面,我们将同一个作业类执行两个任务,并都将他们注册到任务调度器上!     首先一个job类指向两 ...

  7. 企业级任务调度框架Quartz(9) Quartz之作业触发器Trigger

    前序:      我们已经大概对Quartz的基本有了一个大概的认识:现在我们将要逐渐对Quartz的各个重要组件进行学习:前面已经对job进行了详细讲解,现在我们来认识下它的一个重要兄弟,没有它,作 ...

  8. 企业级任务调度框架Quartz(8) 线程在Quartz里的意义(2)

    前序:      做为企业里的任务调度框架,出现同一时间点同时运行两个任务,或者两个任务因为开始的执行时间和执行时间的长短,很有可能出现任务并发执行的情况:因为Quartz的实现是采用java编程,那 ...

  9. 企业级任务调度框架Quartz(3) 一个简单的Quartz 例子

    1. 一个简单的Quartz 工程     本示例应用比起众所周知的 System.out.println("Hello world from Quartz") 来还是要有趣些.当 ...

随机推荐

  1. Golang - 并发编程

    目录 Golang - 并发编程 1. 并行和并发 2. go语言并发优势 3. goroutine是什么 4. 创建goroutine 5. runtime包 6. channel是什么 7. ch ...

  2. 【1】Django概述

    道生一,一生二,二生三,三生万物 无名天地之始,有名万物之母 ——老子 python程序web项目开发,是非常重要的一部分,Python为基础的web项目开发的框架有很多,django无疑是最强大we ...

  3. Spring Cloud系列(三) 应用监控与管理Actuator

    Spring Cloud系列(二) 应用监控与管理Actuator 前言:要想使用Spring Cloud ,Spring Boot 提供的spring-boot-starter-actuator模块 ...

  4. 修改oracle数据库时间

    1.修改前需要先停止 oracle 数据库服务 2.修改 oracle 数据库所在的服务器时间 3.再次启动 oracle 数据库,即可 以上就是小编修改 oracle 数据库的时间,修改完之后,其他 ...

  5. elasticsearch 权威指南聚合阅读笔记(七)

    count(1) select clssId,count(1) from student group by  classId { "size":0, "aggs" ...

  6. Python - 字符串模板的安全替换(safe_substitute) 具体解释

    字符串模板的安全替换(safe_substitute) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/27057339 ...

  7. java构造函数重载this(true)

    看storm的代码的时候,发现这样一句java代码, 很是不理解 google之后,发现原来是java语法中,构造函数重载,this()调用的其实就是 构造函数.This is constructor ...

  8. Linux中修改系统时间

    #date //显示当前日期 #date -s //设置当前时间,只有root权限才能设置,其他只能查看. #date -s 20061010 //设置成20061010,这样会把具体时间设置成空00 ...

  9. luogu3865 【模板】 ST表

    题目大意:给出一段序列,每次查询一段区间,求区间最大值. ST表:设原序列为A,定义F[i][k]为A[i][2k-1]的最大值.有递归式:F[i][k]=max(F[i][k-1], F[i+2k- ...

  10. SpringMVC 拦截器不拦截静态资源的三种处理方式方法

    方案一.拦截器中增加针对静态资源不进行过滤(涉及spring-mvc.xml) <mvc:resources location="/" mapping="/**/* ...