一、Quartz 核心
工作原理:
- Scheduler 是一个计划调度器容器(总部),容器里面可以盛放众多的
JobDetail
和Trigger
。当容器启动后,里面的每个JobDetail
都会根据Trigger
按部就班自动去执行。 - JobDetail 是一个可执行的工作,它本身可能是有状态的。
- Trigger 代表一个调度参数的配置,什么时候去调。
- 当
JobDetail
和Trigger
在Scheduler
容器上注册后,形成了装配好的作业(JobDetail
和Trigger
所组成的一对儿),就可以伴随容器启动而调度执行了。 - Scheduler 是个容器,容器中有一个线程池,用来并行调度执行每个作业,这样可以提高容器效率。
概念详解:
-
Job
- 作业是一个执行任务的简单 Java 类。任务可以是任何 Java 代码。只需实现
org.quartz.Job
接口,并将需要执行的任务代码写在execute()
方法中即可。当 Quartz 确定该是作业运行的时候,它将调用你的作业。Quartz 提供了一个机制来建立具有不同粒度的、可重复的调度表,于是,你只需创建一个 Java 类,这个类被调用而执行任务。
public interface Job {void execute(JobExecutionContext context) throws JobExecutionException; }Class MyJob implements Job {@Override void execute(JobExecutionContext context) { // 任务执行代码} }
- 作业是一个执行任务的简单 Java 类。任务可以是任何 Java 代码。只需实现
-
JobDetail
JobDetail
对象由 Quartz 客户端在 Job 被加入到Scheduler
时创建。它包含了 Job 的各种设置属性以及一个JobDataMap
对象,这个对象被用来存储给定 Job 类实例的状态信息。Scheduler
并不保存真正的 Job Class,而是通过JobDetail
来保存。- 注意,给
Scheduler
传入了一个JobDetail
实例,而且这个JobDetail
实例只是简单提供了类名来引用被执行的 Job。每次Scheduler
执行这个任务时,它就创建这个类的新实例,然后调用该实例的execute(..)
方法。Job 不必担心线程安全性,因为同一时刻仅有一个线程去执行给定 Job 类的实例,甚至是并发执行同一 Job 也是如此。
-
JobFactory
JobFactory
控制 Job 的实例化
Job newJob(TriggerFiredBundle bundle) throws SchedulerException;
- 默认的
JobFactory
是org.quartz.simpl.SimpleJobFactory
,缺省的JobFactory
只是简单地对 Job 类调用newInstance()
方法。 - 设置
JobFactory
:
scheduler.setJobFactory(factory);
- 配置
quartz.properties
的org.quartz.scheduler.jobFactory.class
属性设置JobFactory
的类型
-
JobDataMap
JobDataMap
被用来保存一系列的(序列化的)对象,这些对象在 Job 执行时可以得到。JobDataMap
是 JavaMap
接口的一个实现,而且还增加了一些存储和读取主类型数据的便捷方法。- 设置:
JobDetail.getJobDataMap().put("jobSays", "Hello World!");
- 获取:
JobExecutionContext.getJobDetail().getJobDataMap();
Trigger.getJobDataMap();
JobExecutionContext.getMergedJobDataMap();
-
StatefulJob
- 有状态任务在执行任务过程中,任何对
JobDataMap
所作的更改都将丢失而且任务下次执行时也无法看到。 StatefulJob
在任务的每次执行之后重新存储JobDataMap
。
- 有状态任务在执行任务过程中,任何对
-
Trigger(触发器)
Trigger
对象被用来触发 jobs 的执行。你希望将任务纳入到进度,要实例化一个Trigger
并且“调整”它的属性以满足你想要的进度安排。Triggers
也有一个JobDataMap
与之关联,这非常有利于向触发器所触发的 Job 传递参数。Quartz 打包了很多不同类型的Trigger
, 最常用的Trigger
类是SimpleTrigger
和CronTrigger
。
-
SimpleTrigger
SimpleTrigger
用来触发只需执行一次或者在给定时间触发并且重复 N 次且每次执行延迟一定时间的任务。- 例如,如果你想让触发器在2010年1月11日,上午11:23:54秒执行,然后每隔10秒钟重复执行一次,并且这样重复5次,那么
SimpleTrigger
就可以满足你的要求。
-
CronTrigger
- 如果你需要像日历那样按日程来触发任务,而不是像
SimpleTrigger
那样每隔特定的间隔时间触发,CronTriggers
通常比SimpleTrigger
更有用。 - 使用
CronTrigger
,你可以指定诸如“每个周五中午”,或者“每个工作日的9:30”或者“从每个周一、周三、周五的上午9:00到上午10:00之间每隔五分钟”这样日程安排来触发。甚至,象SimpleTrigger
一样,CronTrigger
也有一个startTime
以指定日程从什么时候开始,也有一个(可选的)endTime
以指定何时日程不再继续。
public CronTrigger(String name, String group, String jobName, String jobGroup, Date startTime, Date endTime, String cronExpression, TimeZone timeZone) throws ParseException;
- 如果你需要像日历那样按日程来触发任务,而不是像
-
Cron Expressions
Cron
表达式被用来配置CronTrigger
实例。Cron
表达式是一个由7个子表达式组成的字符串。每个子表达式都描述了一个单独的日程细节。这些子表达式用空格分隔,分别表示:- Seconds 秒
- Minutes 分钟
- Hours 小时
- Day-of-Month 月中的天
- Month 月
- Day-of-Week 周中的天
- Year (optional field) 年
-
TriggerUtils
TriggerUtils
提供了许多便捷的方法简化了构造和配置Trigger
。
public static Trigger makeSecondlyTrigger(int intervalInSeconds); public static Trigger makeDailyTrigger(int hour, int minute); public static Trigger makeWeeklyTrigger(int dayOfWeek, int hour, int minute); public static Trigger makeMonthlyTrigger(int dayOfMonth, int hour, int minute); public static Date getNextGivenMinuteDate(Date date, int minuteBase); public static Date getEvenMinuteDate(Date date);