StdScheduler 通过文件加载的方式初始化Schedule工厂
// Create an instance of the factory
StdSchedulerFactory factory = new StdSchedulerFactory();
// Create the properties to configure the factory
Properties props = new Properties();
// required to supply threadpool class and num of threads
props.put(StdSchedulerFactory.PROP_THREAD_POOL_CLASS,
"org.quartz.simpl.SimpleThreadPool");
props.put("org.quartz.threadPool.threadCount", "10");
// Initialize the factory with properties
factory.initialize(props);
Scheduler scheduler = factory.getScheduler();
DirectSchedulerFactory通过硬编码的方式初始化Scheduler工厂
DirectSchedulerFactory factory=DirectSchedulerFactory.getInstance();
// Initialize the Scheduler Factory with 10 threads
factory.createVolatileScheduler(10);
// Get a scheduler from the factory
Scheduler scheduler = factory.getScheduler();
Scheduler生命周期中的方法
scheduler.start(); 开始
scheduler.shutdonw(); 结束
注意:别在 shutdown() 之后调用 start()
Scheduler 实例被关闭之后你就不能调用它的 start() 方法了。这是因为 shutdown() 方法销毁了为
Scheduler 创建的所有的资源(线程,数据库连接等)。假如你在 shutdown() 之后调用 start()你将
收到 SchedulerException 的异常。
org.quartz.Job 接口
把 Quartz 作用到 Java 类上唯一要做的就是让它实现 org.quartz.Job 接口。你的 Job 类可以实现
任何其他想要的接口或继承任何需要的基类,但是它自己或是它的超类必须实现这个 Job 接口。这个
Job 接口只定义了单个方法:
public void execute(JobExecutionContext context)
throws JobExecutionException;
JobExecutionContext
当 Scheduler 调用一个 Job,一个 JobexecutionContext 传递给 execute() 方法。
JobExecutionContext 对象让 Job 能访问 Quartz 运行时候环境和 Job 本身的明细数据。
JobDetail
对于部署在 Scheduler 上的每一个 Job 只创建了一个 JobDetail 实例。JobDetail 是作为 Job 实
例进行定义的
JobDataMap
org.quartz.JobDataMap 来定义 Job 的状态。JobDataMap 通过它的超类 org.quartz.util.DirtyFlagMap
实现了 java.util.Map 接口,你可以向 JobDataMap 中存入键/值对,那些数据对可在你的
Job 类中传进行访问。这是一个向你的 Job 传送配置的信息便捷方法。
// Every job has its own job detail
JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
使用有状态的 Job
当你需要在两次 Job 执行间维护状态的话,Quartz 框架为此提供了 org.quartz.StatefulJob 接口。
StatefulJob 接口仅仅是扩展了 Job 接口,未加入新的方法。你只需要通过使用与 Job 接口相同的
execute() 方法简单的实现 StatefulJob 接口即可。假如你有已存在的 Job 类,你所有要做的只是
改变 Job 的接口为 org.quartz.StatefulJob。
改变有状态 Job 的 JobDataMap
你可以在有状态 Job 中简单的通过 map 的 put() 方法来修改 JobDataMap.已存在的任何数据会被新
的数据覆盖掉。你也能对无状态的 Job 这么做,但是因为对于无状态 Job 来说,JobDataMap 不会持
久化,所以数据不会保存下来。对于 Trigger 和 JobExecutionContext 上的 JobDataMap 的数据修改
也是没能保存下来的。
Job 的易失性
一个易失性的 Job 是在程序关闭之后不会被持久化。一个 Job 是通过调用 JobDetail 的
setVolatility(true) 被设置为易失性的。
当你需要持久化 Job 时不应使用 RamJobStore,RamJobStore 使用的是非永久性存储器,
所有关于 Job 和 Trigger 的信息会在程序关闭之后丢失。保存 Job 到 RamJobStore 有效的使得它们
是易失性的。假如你需要让你的 Job 信息在程序重启之后仍能保留下来,你就该考虑另一种 JobStore
类型,比如 JobStoreTX 或者 JobStoreCMT。
Job 持久性
一个持久的 Job 是它应该保持在 JobStore 中的,甚至是在没有任何 Trigger 去触发它的时候。我们
说,你设置了一个单次触发的 Trigger,触发之后它就变成了 STATE_COMPLETE 状态。Job 执行一次后
就不再被触发了,这个 Trigger 部署之后只为了执行一次。这个 Trigger 指向的 Job 现在成了一个
孤儿 Job,因为不再有任何 Trigger 与之相关联了。
假如你设置一个 Job 为连续性的,即使它成了孤儿 Job 也不会从 JobStore 移除掉。这样可以保证在
将来,无论何时你的程序决定为这个 Job 增加另一个 Trigger 都是可用的。假如调用了 JobDetail 的
setDurability(false) 方法,那么在所有的触发器触发之后 Job 将从 JobStore 中移出。连续性的默
认值是 false。因此,Job 和 Trigger 的默认行为是:当 Trigger 完成了所有的触发、Job 在没有
Trigger 与之关联时它们就会从 JobStore 中移除。
Job 的可恢复性
当一个 Job 还在执行中,Scheduler 经历了一次非预期的关闭,在 Scheduler 重启之后可恢复的 Job
还会再次被执行。这个 Job 会再次重头开始执行。Scheduler 是没法知道在程序停止的时候 Job 执行
到了哪个位置,因此必须重新开始再执行一遍。要设置 Job 为可恢复性,用下面的方法:
public void setRequestsRecovery(boolean shuldRecover);
默认时,这个值为 false,Scheduler 不会试着去恢复 job 的。
Scheduler 中移除 Job
多种方式移除已部署的 Job。一种方式是移除所有与这个 Job 相关联的 Trigger;如果这个 Job 是非持久
性的,它将会从 Scheduler 中移出。一个更简单直接的方式是使用 deleteJob() 方法:
public boolean deleteJob(String jobName, String groupName)throws SchedulerException;
中断 Job
Quartz 包括一个接口叫做 org.quartz.InterruptableJob,它扩展了普通的 Job 接口并提供了一个
interrupt() 方法:
public void interrupt() throws UnableToInterruptJobException;
可以提供 Job 部署时所用的 Job 的名称和组名调用 Scheduler 的 interrupte() 方法:
public boolean interrupt(SchedulingContext ctxt, String jobName, String groupName) throws
UnableToInterruptJobException;
框架所提供的 Job
org.quartz.jobs.FileScanJob 检查某个指定文件是否变化,并在文件被改变时通知到相应监听器的 Job
org.quartz.jobs.FileScanListener 在文件被修改后通知 FileScanJob 的监听器
org.quartz.jobs.NativeJob 用来执行本地程序(如 windows 下 .exe 文件) 的 Job
org.quartz.jobs.NoOpJob 什么也不做,但用来测试监听器不是很有用的。一些用户甚至仅仅用它来导致
一个监听器的运行
org.quartz.jobs.ee.mail.SendMailJob 使用 JavaMail API 发送 e-mail 的 Job
org.quartz.jobs.ee.jmx.JMXInvokerJob 调用 JMX bean 上的方法的 Job
org.quartz.jobs.ee.ejb.EJBInvokerJob 用来调用 EJB 上方法的 Job
主处理线程:QuartzSchedulerThread
Quartz 应用第一次运行时,main 线程会启动 Scheduler。QuartzScheduler 被创建并创建一个
org.quartz.core.QuartzSchedulerThread 类的实例。QuartzSchedulerThread 包含有决定何时下一个
Job 将被触发的处理循环。顾名思义,QuartzSchedulerThread 是一个 Java 线程。它作为一个非守护线
程运行在正常优先级下。
QuartzSchedulerThread 的主处理循环的职责描述如下:
1. 当 Scheduler 正在运行时:
A. 检查是否有转换为 standby 模式的请求。
1. 假如 standby 方法被调用,等待继续的信号
B. 询问 JobStore 下次要被触发的 Trigger.
1. 如果没有 Trigger 待触发,等候一小段时间后再次检查
2. 假如有一个可用的 Trigger,等待触发它的确切时间的到来
D. 时间到了,为 Trigger 获取到 triggerFiredBundle.
E. 使用 Scheduler 和 triggerFiredBundle 为 Job 创建一个 JobRunShell 实例
F. 告诉 ThreadPool 可能时运行 JobRunShell.
这个逻辑存在于 QuartzSchedulerThread 的 run() 方法中。
QuartzSchedulerResources
当工厂创建 Scheduler 实例时,它还会传递给 Scheduler 一个 org.quartz.core.QuartzSchedulerResoures
实例。QuartzSchedulerResourecs 除包含以上东西之后,还有一个 ThreadPool 实例,它提供了一个工作者
线程池来负责执行 Job。在 Quartz 中,ThreadPool 是由 org.quartz.spi.ThreadPool 接口 (因为 Quartz
是在 JDK 1.5 之前产生的,所以需要自己的 ThreadPool 类确保向后的兼容性,Quartz 仍然用自己的
ThreadPool 替代 Java 的) 表示的,并提供一个名为 org.quartz.simp.SimpleThreadPool 的具体实现类。
SimpleThreadPool 有一个固定数目的工作者线程,在加载之后就不再减少或增多
Quartz 工作者线程
Quartz 不会在 main 线程中处理你的 Job。如果这么做,会严重降低应用的可扩展性。相应的,Quartz
把线程管理的职责委托给分散的组件。对于一般的 Quartz 设置 (这部分还是很费功夫的),都是用
SimpleThreadPool 类处理线程的管理。SimpleThreadPool 创建了一定数量的 WorkerThread 实例来使得
Job 能够在分散的线程中进行处理。WorkerThread 是定义在 SimpleThreadPool 类中的内部类,它实质上就是
一个线程。要创建 WorkerThread 的数量以及为他们的优先级是配置在文件 quartz.properties 中并传入工厂的
JobRunShell 的 run() 方法
虽然 WorkerThread 是真正的 Java 线程,JobRunShell 类也还是实现了 Runable。那意味着它可以作为一个
线程并包含一个 run() 方法。在本章前面讨论过,JobRunShell 的目的是调用 Job 的 execute() 方法。
不仅如此,它还要负责通知 Job 和 Trigger 监听器,在运行完成后还得更新此次执行的 Trigger 的信息。
org.quartz.SimpleTrigger
正如其名所示,SimpleTrigger 对于设置和使用是最为简单的一种 Quartz Trigger。它是为那种需要在特定
的日期/时间启动,且以一个可能的间隔时间重复执行 n 次的 Job 所设计的。
org.quartz.CronTrigger
CronTrigger 允许设定非常复杂的触发时间表,顾名思义,CronTrigger 是基于 Unix 类似于 cron 的表达式。
org.quartz.NthIncludedDayTrigger
它设计用于在每一间隔类型的第几天执行 Job。Quartz 的 Caldendar 也可与 Trigger 关联以此把周末与
节假日考虑进来,并在必要时跳开这些日期。
为一个 Job 使用多个 Trigger
单个 JobDetail 能够支持多个 Trigger,但一个 Trigger 只能被指派给一个 Job。
org.quartz.Calendar
Quartz 定义了 org.quartz.Calendar 接口,所有的 Quartz Calendar 必须实现它。它包含了几个方法,
但是有两个是最重要的:
public long getNextIncludedTime(long timeStamp);
public boolean isTimeIncluded(long timeStamp);
作为一个 Quartz Job 的创建者和开发者,你可不必去熟悉 Calender 接口。这主要是因为已有的 Calendar
(Quartz 自带的) 需要应付的情况就不够多。开箱即用的,Quartz 包括许多的 Calender 实现足以满足你的要求
org.quartz.impl.calendar.BaseCalender 为高级的 Calender 实现了基本的功能,实现了
org.quartz.Calender 接口
org.quartz.impl.calendar.WeeklyCalendar 排除星期中的一天或多天,例如,可用于排除周末
org.quartz.impl.calendar.MonthlyCalendar 排除月份中的数天,例如,可用于排除每月的最后一天
org.quartz.impl.calendar.AnnualCalendar 排除年中一天或多天
org.quartz.impl.calendar.HolidayCalendar 特别的用于从 Trigger 中排除节假日
Calendar examle
// Create an instance of the Quartz AnnualCalendar
AnnualCalendar cal = new AnnualCalendar();
// exclude July 4th
Calendar gCal = GregorianCalendar.getInstance();
gCal.set(Calendar.MONTH, Calendar.JULY);
gCal.set(Calendar.DATE, 4);
cal.setDayExcluded(gCal, true);
// Add to scheduler, replace existing, update triggers
scheduler.addCalendar("bankHolidays", cal, true, true);
/*
* Set up a trigger to start firing now, repeat forever
* and have (60000 ms) between each firing.
*/
Trigger trigger = TriggerUtils.makeImmediateTrigger("myTrigger", -1,60000);
trigger.setCalendarName("bankHolidays");
//HolidayCalender 类考虑的是年份。因此,如果你希望在后续三年中排除 7 月 4 日,
//你需要把三年中的每个日期都作为要排除的项。而 AnnualCalender 可简单的为每年
//设定要排除的日期
CronTrigger 使用起迄日期
CronTrigger 的 setStartTime() 和 setEndTime() 方法来形成一个 "定时箱" 来触发。
JobStore 接口
Quartz 为所有类型的 Job 存储提供了一个接口。这个接口位于 org.quartz.spi 包中,叫做
JobStore。所有的 Job 存储机制,不管是在哪里或是如何存储他们的信息的,都必须实现这个接口。
分享到:
相关推荐
这个学习笔记将深入探讨Quartz的核心概念、主要功能以及如何在实际项目中使用它。 首先,我们要理解Quartz的基本架构。Quartz的核心组件包括Scheduler、Job、Trigger和Calendar。Scheduler是调度器,负责管理所有的...
Quartz 是一个强大的任务调度框架,由 OpenSymphony 开源组织开发,主要目的是提供一个用于在 Java 应用程序中安排任务执行的解决方案。Quartz 支持与 J2EE 和 J2SE 平台的无缝集成,允许开发者在各种类型的项目中...
刘冬编写Spring.NET学习笔记25——整合Quartz.NET例子。 原文: http://www.cnblogs.com/GoodHelper/archive/2009/11/20/SpringNet_QuartzNet.html
本学习笔记主要围绕Quartz的使用,特别是如何利用corn表达式来设置定时任务。 Quartz的核心概念包括Job(任务)、Trigger(触发器)和Scheduler(调度器)。Job是你要执行的实际业务逻辑,Trigger定义了Job何时被...
Quartz是一款开源的作业调度框架,它允许开发者创建和管理定时任务,以便在特定时间执行。在Java世界中,Quartz被广泛应用于...通过实践和学习,你将能够熟练掌握Quartz的使用,为你的项目带来更高效的自动化处理能力。
六、Quartz学习资源 本教程、学习手册和帮助手册将详细阐述Quartz的各个方面,从基本使用到高级特性的实践,帮助开发者从初学者到精通者。通过阅读这些资料,你可以掌握如何在项目中有效地使用Quartz,提升系统的...
Spring Boot 是一个基于 Spring 框架的快速开发...这个完整的 Spring Boot 学习笔记涵盖了从基础到进阶的各个方面,通过学习和实践,你可以掌握 Spring Boot 开发的核心技能,从而高效地构建高质量的 Java 后端应用。
NULL 博文链接:https://jaykuen.iteye.com/blog/911106
【学习笔记 MHT2】是一份综合性的IT学习资料,主要涵盖了JavaScript编程、软件开发工具、Web服务器技术、编码解码方法以及设计模式等多个领域的知识。以下是对这些知识点的详细阐述: 1. **JavaScript经典技巧**:...
标题中的“spring2.0学习笔记+spring定时任务”表明了这个压缩包文件包含的是关于Spring框架2.0版本的学习资料,特别是关于Spring的定时任务功能。Spring是Java开发中最广泛应用的轻量级框架之一,它提供了一整套...
学习笔记中可能包含了一些关于Objective-C图形编程的内容,如Core Graphics或Quartz 2D,它们是苹果平台进行低级绘图的API,可用于创建自定义视图和复杂的图形。 六、实践应用 理论学习后,通过编写简单的iOS应用...
这个“spring学习笔记”包含了与Spring框架相关的源代码和项目实践,旨在帮助学习者深入理解并掌握Spring的核心概念和技术。 首先,Spring的核心特性之一是依赖注入(Dependency Injection, DI),它允许开发者通过...
《若依RuoYi框架剖析笔记》是基于江南一点雨的课程并结合个人理解整理而成,涵盖了项目改造、框架结构分析以及多个关键功能模块的深入探讨。以下将逐一解析这些知识点。 1、**项目改造**:首先,从源代码仓库获取...
SpringBoot学习笔记完整教程 SpringBoot是Spring框架的一个简化版,旨在简化Spring应用程序的初始设置和开发过程。它集成了大量的常用库,如数据访问、安全、Web等,使得开发者可以快速构建健壮的微服务应用。本...
这个“Spring学习笔记(内含代码)”包含了作者在深入研究Spring框架过程中所做的详细记录,旨在帮助初学者和有经验的开发者更好地理解和应用Spring。 Spring框架的核心特性包括依赖注入(Dependency Injection,DI...
如果你使用Visual C++(VC),则需要在项目设置中包含`Dshow.h`头文件和`Strmiids.lib`及`Quartz.lib`库。`Strmiids.lib`包含了所有接口的CLSID和IID定义,而`Quartz.lib`则是必需的库文件。 一个简单的DirectShow...