定时器(Quartz)使用说明
本文目前主要包括如下几个部分:
Quartz功能简介 :介绍Quartz的特点及概念。
使用Quartz的常见问题 :很多用户在使用过程中遇到常见问题的解答。
快速开始:让读者尽快掌握Quartz开发。
Quartz官方开发指南:通过一些列的课程来指导如何使用Quartz.
Quartz 功能简介
Quartz 特点:
z Quartz 能嵌入到任何独立的应用中运行。
z Quartz 能在应用服务器或者 Servlet 容器中实例化,并且能够参与 XA 事务。
z Quartz 能够以独立的方式运行(在它自己的 Java 虚拟机中),可以通过 RMI 使用
Quartz。
z Quartz 可以被实例化为独立程序的集群(有负载均衡和容错能力)。
Job Scheduling(任务日程安排)
任务在给定的触发器(Trigger)触发时执行。触发器可以通过几乎以下所有形式的组
合方式进行创建:
z 在一天中的任意时刻(可以精确到毫秒)。
z 一周中特定的一些天。
z 一个月中特定的一些天。
z 一年中特定的一些天
z 不在日历列表中注册的一些天(比如节假日)。
z 循环特定的次数。
z 循环到特定的时间。
z 无限循环。
z 按照一定的时间间隔循环。
“任务”由创建者给定名字,并且可以加入到给定名称的“任务组”中。为了简化触
发器在日程中的管理,“触发器”也可以被给定名字和分组。任务只能加入到日程中一次,
但是可以为其注册多个触发器。在 J2EE 环境中,任务可以作为分布(XA)事务的一部分执
行。
Job Execution(任务执行)
• 任务是任何实现简单 Job 接口的 Java 类,这样开发者能够执行任何完成他们工作
的任务。
• 任务类的实例可以由 Quartz 实例化,也可以由你的程序框架实例化。
当触发器被触发时,日程管理器将会通知某个或者多个实现了 JobListener 或
TriggerListener 的对象(监听器可以是简单的 Java 对象,或者 EJBs,或者 JMS 消息
发布器,等等)。这些监听器在任务执行完毕后也会接到通知。
• 任务被完成后,他们会返回一个“任务完成码(JobCompletionCode)”,这个
“任务完成码”告知日程管理器任务执行的结果是成功还是失败。日程管理器会根
据成功或者失败码来采取措施,比如:立即重新执行任务。
Job Persistence(任务持久化)
• Quartz 设计中包括了一个 JobStore 接口,这样,实现这个接口的 Job 类可以以
多种机制实现 Job 的存储。
• 通过使用 JDBCJobStore,所有的 Jobs 和 Triggers 被配置为“non-volatile”(不
轻快)的方式。即,通过 JDBC 存储在关系数据库中。
• 通过使用 RAMJobStore,所有 Jobs 和 Triggers 被存储在 RAM。因此,在程序
执行中没有被持久化,但这种方式的优点就是不需要外部数据库。
Transactions(事务)
• Quartz 通过 JobStoreCMT(JDBCJobStore 的一个子类)可参与 JTA 事务。
• Quartz 可以管理 JTA 事务(开始或者提交事务)。
Clustering(集群)
• Fail-over.(容错)
• Load balancing.(负载均衡)
Listeners & Plug-Ins(监听器及插件)
• 应用可以通过实现一个或者多个监听器接口来实现捕捉日程事件,以监视或控制任
务/触发器的行为。
• 可以通过插件的机制来扩展 Quartz 的功能。例如:记录任务执行历史的日志,或
者从文件中载入任务和触发器的定义。
• Quartz 自带了一些“factory built(内建)”的插件和监听器。
常见问题
一般问题
• Quartz是什么?
• 为什么不使用java.util.Timer?
• 如何build Quartz源码?
杂项问题
• Quartz可以运行多少任务?
• 通过RMI使用Quartz存在一些问题。
关于 Jobs 的问题
• 如何能够控制Jobs的实例化。
• 如何避免一个任务在完成后被移(删)除?
• 如何避免一个Job被并发激活?
• 如何停止一个正在执行的任务?
关于触发器的问题:
• 如何串行任务的执行?或者,如何能够创建一个工作流程?
• 为什么触发器没有被触发?
• 夏令时和触发器
关于 JDBCJobStore 的问题
• 如何提高JDBC-JobStore的性能?
• 如果数据服务器重新启动,DB连接不能够正确恢复
关于事务的问题
• 使用JobStoreCMT并且发现了死锁,该如何做?
General Questions 一般问题
Quartz 是什么?
Quartz 是一个任务日程管理系统,这个系统可以与任何其他软件系统集成或者一起
使用。术语“日程进度管理器”可能对于不同的人有不同的理解。当你阅读这个指南之后,
你会对这个术语有固定的理解。简而言之,“任务进度管理器”就是一个在预先确定(被
纳入日程)的时间到达时,负责执行(或者通知)其他软件组件的系统。
为了达到预想目的,或者是能够写出与工程最“自然”衔接的软件代码,Quartz 相
地灵活,并且包括了多个用法范例,可以单独运用这些范例或者组合运用这些范例。
Quartz 相当“轻量”,并且需要非常少的步骤/配置,如果需求比较基本,Quartz
确实非常容易使用。
Quartz 具有容错性,并且可以在你系统重起的时候持久化(记住)被纳入日程的任
务。
虽然 Quartz 对于按照简单地给定日程运行的系统时非常有用,但是,当你学会如何
使用它来驱动你应用中的商务过程,那么你才会认识到它的全部潜能。
从软件组件的角度来看,Quartz 是什么?
Quartz 用一个小 Java 库发布文件(.jar 文件),这个库文件包含了所有 Quartz 核
心功能。这些功能的主要接口(API)是 Scheduler 接口。它提供了简单的操作,例如:将
任务纳入日程或者从日程中取消,开始/停止/暂停日程进度。
如果你想将软件组件的执行纳入到日程中,它们只需简单地实现 Job 接口,这个接口
有一个 execute()方法。如果希望在日程安排的时间到达时通知组件,那么这些组件应实
现 TriggerListener 或者 JobListener 接口。
Quartz 主过程可以在应用中启动或者运行,也可以作为一个独立的应用(带有 RMI
接口),或者在一个 J2EE 应用服务器中运行,并且可作为其它 J2EE 组件的一种引用资
源。
为什么不使用 java.util.Timer?
从 JDK1.3 开始,Java 有了内建的定时器功能,即,通过 java.util.Timer 和
java.util.TimerTask 来实现,为什么有人用 Quartz 而不用这些标准特性呢?有很多原
因,下面是其中的一些:
1. Java 定时器没有持久化机制。
2. Java 定时器的日程管理不够灵活(只能设置开始时间、重复的间隔,设置特定的日
期、时间等)
3. Java 定时器没有使用线程池(每个 Java 定时器使用一个线程)
4. Java 定时器没有切实的管理方案,你不得不自己完成存储、组织、恢复任务的措施。
...当然,对于某些简单的应用来说,这些特性可能不那么重要,在这种情况下,不使用
Quartz 也是正确的选择。
如何 build Quartz 源码?
尽管 Quartz 以“预先编译”的形式打包。很多人可能想做他们自己的改变或者 buil
从 CVS 上得到的最新的“未发布”的 Quartz 版本。阅读随同 Quartz 一起打包的
"README.TXT"文件就知道怎么做。
Miscellaneous Questions 杂项问题
Quartz 可以运行多少任务?
这是一个比较难以回答的问题,答案基本上是“看它依赖于什么环境”。
你可能不喜欢这个答案,这里有一些关于它所依赖环境的信息。
首先,JobStore 对性能有重要的影响.基于 RAM 的 JobStore 要比基于 JDBC 的
JobStore 快的多。基于 JDBC 的 JobStore 的速度几乎完全取决于对数据库连接的速度,
以及使用的数据系统以及数据库运行的硬件。Quartz 本身实际上只做很少的处理,差不
多所有的时间都花费在数据库上。当然,RAMJobStore 对于有多少“任务”或者“触发
器”可以存储是有数量限制的,因为,内存的数量要比数据库的硬盘空间小的多。你可以
参考问题“如何提高 JDBC-JobStore 的性能?”。
因此,对于 Quartz 能存储和监控的触发器和任务的数量限制因素时间上是 JobStore
有多少可用的存储空间的数量。(内存数量或者是硬盘数量)。
现在,除了“能存储多少?”的问题之外,就是“Quartz 能同时运行多少个任务?”
能够使 Quartz 本身运行变慢的就是使用大量的监听器(TriggerListeners,
JobListeners, 和 SchedulerListeners),除了任务本身实际的运行时间外,花费在每
个监听器上的时间会直接记入“处理”任务的执行时间上。这不意味着因此而害怕使用监
听器,而是说要明智地使用监听器。如果能够使用特定的监听器就不要创建大量“全局”
监听器,也不要使用监听器作“耗时”的工作,除非必须做。另外,也要留心,很多插件
实际上也是监听器(例如:“history”插件)。
同时能够运行多少个任务受限于线程池的大小。如果池中有 5 个线程,则同时可运行
的任务不超过 5 个。使用大量线程时要小心,因为 JVM,操作系统和 CPU 处理大量线程时
很耗时,并且,线程管理也会导致性能下降。在多数情况下,性能开始下降是因为使用多
达数百个线程。如果在应用服务器中运行程序,要留心应用服务器本身已经创建了不少的
线程。
除了这些因素外,还同要执行的任务有关,如果任务需要花费很长时间才能完成它们
的工作,并且(或者)它们的工作很消耗 CPU,那么很明显不要同时运行多个任务,也不
要在一个时间段内运行过多这样的任务。