参考:https://www.w3cschool.cn/quartz_doc/
核心组成
- Job:表示一个工作,要执行的具体内容。此接口中只有一个方法,如下:void execute(JobExecutionContext context)
- JobDetail 表示一个具体的可执行的调度程序,Job 是这个可执行程调度程序所要执行的内容,另外 JobDetail 还包含了这个任务调度的方案和策略。
- Trigger 代表一个调度参数的配置,什么时候去调。
- Scheduler 代表一个调度容器,一个调度容器中可以注册多个 JobDetail 和 Trigger。当 Trigger 与 JobDetail 组合,就可以被 Scheduler 容器调度了。
使用案例
SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
Scheduler sched = schedFact.getScheduler();
sched.start();
JobDetail job = newJob(HelloJob.class)
.withIdentity("myJob", "group1")
.build();
Trigger trigger = newTrigger()
.withIdentity("myTrigger", "group1")
.startNow()
.withSchedule(simpleSchedule()
.withIntervalInSeconds(40)
.repeatForever())
.build();
// Tell quartz to schedule the job using our trigger
sched.scheduleJob(job, trigger);
Job和JobDetail任务
定义:
- 实现Job接口的类:job类
- JobDetail对象:job定义,JobDetail实例
- 正在执行的job:job实例,job定义的实例
JobDataMap(job的状态数据)
- 可以存储对象(序列化)
- 可以自动化注入到job类的变量
job类的注解:
- @DisallowConcurrentExecution:禁止同一时刻并发执行同个job实例
- @PersistJobDataAfterExecution:将该注解加在job类上,告诉Quartz在成功执行了job类的execute方法后(没有发生任何异常),更新JobDetail中JobDataMap的数据,使得该job(即JobDetail)在下一次执行的时候,JobDataMap中是更新后的数据,而不是更新前的旧数据。
JobExecutionException
Triggers触发器
有两种Trigger
- SimpleTrigger
- CronTrigger
Trigger的属性
- TriggerKey:唯一标识,一般由group和name组成
- jobKey属性:当trigger触发时被执行的job的身份;
- startTime属性:表示trigger的开始时间点
- endTime属性:表示trigger失效的时间点
- 优先级(priority):为两个同时发生的trigger设置优先级,默认优先级为5;
- 错过触发(misfire Instructions):如果scheduler关闭了,或者Quartz线程池中没有可用的线程来执行job,此时持久性的trigger就会错过(miss)其触发时间,即错过触发(misfire)。不同类型的trigger,有不同的misfire机制。
- 日历示例(calendar):Calendar用于从trigger的调度计划中排除时间段。比如,可以创建一个trigger,每个工作日的上午9:30执行,然后增加一个Calendar,排除掉所有的商业节日。
Simple Trigger
SimpleTrigger可以满足的调度需求是:在具体的时间点执行一次,或者在具体的时间点执行,并且以指定的间隔重复执行若干次。比如,你有一个trigger,你可以设置它在2015年1月13日的上午11:23:54准时触发,或者在这个时间点触发,并且每隔2秒触发一次,一共重复5次。
例如
指定时间触发,每隔10秒执行一次,重复10次:
trigger = newTrigger()
.withIdentity("trigger3", "group1")
.startAt(myTimeToStartFiring) // if a start time is not given (if this line were omitted), "now" is implied
.withSchedule(simpleSchedule()
.withIntervalInSeconds(10)
.withRepeatCount(10)) // note that 10 repeats will give a total of 11 firings
.forJob(myJob) // identify job with handle to its JobDetail itself
.build();
SimpleTrigger的Misfire策略常量:
MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY
MISFIRE_INSTRUCTION_FIRE_NOW
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT
CronTrigger
和SimpleTrigger一样,CronTrigger有一个startTime,它指定何时生效,以及一个(可选的)endTime,用于指定何时停止计划。
但是,CronTrigger通常比Simple Trigger更有用,您可以基于日历的概念来启动计划。
Cron Expressions表达式
Cron Expressions是由七个子表达式组成的字符串,用于描述日程表的各个细节。这些子表达式用空格分隔,并表示:
- Seconds
- Minutes
- Hours
- Day-of-Month
- Month
- Day-of-Week
- Year (optional field)
例如:建立一个触发器,每隔一分钟,每天上午8点至下午5点之间
import static org.quartz.TriggerBuilder.*;
import static org.quartz.CronScheduleBuilder.*;
import static org.quartz.DateBuilder.*:
trigger = newTrigger()
.withIdentity("trigger3", "group1")
.withSchedule(cronSchedule("0 0/2 8-17 * * ?"))
.forJob("myJob", "group1")
.build();
CronTrigger Misfire:
MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY
MISFIRE_INSTRUCTION_DO_NOTHING
MISFIRE_INSTRUCTION_FIRE_NOW
TriggerListeners和JobListeners
- TriggerListeners用于监听触发器(trigger)相关的事件,包括:触发器触发,触发失灵,触发完成(触发器关闭的作业完成)。
- JobListeners 用于监听jobs相关的事件,包括:job即将执行的通知,以及job完成执行时的通知。
创建监听器
- 创建一个实现org.quartz.TriggerListener或org.quartz.JobListener接口的对象
- 扩展JobListenerSupport类或TriggerListenerSupport类
例如
import static org.quartz.JobKey.*;
import static org.quartz.impl.matchers.KeyMatcher.*;
import static org.quartz.impl.matchers.GroupMatcher.*;
import static org.quartz.impl.matchers.AndMatcher.*;
import static org.quartz.impl.matchers.OrMatcher.*;
import static org.quartz.impl.matchers.EverythingMatcher.*;
scheduler.getListenerManager().addJobListener(myJobListener, jobKeyEquals(jobKey("myJobName", "myJobGroup")));
SchedulerListeners
SchedulerListeners用于监听调度相关的时间,比如:添加job/触发器,删除job/触发器,调度程序中的严重错误,关闭调度程序的通知等。
创建监听器,只需要实现org.quartz.SchedulerListener接口,然后注册到ListenerManager。
//添加SchedulerListener:
scheduler.getListenerManager().addSchedulerListener(mySchedListener);
//删除SchedulerListener:
scheduler.getListenerManager().removeSchedulerListener(mySchedListener);
Job Stores
三种JobStore方式
- RAMJobStore,所有调度数据存储在RAM内存
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
- JDBCJobStore,将调度数据存储在数据库,有两种JDBCJobStore。JobStoreTX和JobStoreCMT ,主要区别在于如果您需要Quartz与其他事务(即J2EE应用程序服务器)一起工作,那么您应该使用JobStoreCMT - 在这种情况下,Quartz将让应用程序服务器容器管理事务。
//设置JobStore
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreCMT
//设置驱动委托类
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
//设置表前缀
org.quartz.jobStore.tablePrefix = QRTZ_
//设置数据源
org.quartz.jobStore.dataSource = myDS
- TerracottaJobStore,数据存储在Terracotta服务器,可以以集群或非集群方式运行。
org.quartz.jobStore.class = org.terracotta.quartz.TerracottaJobStore
org.quartz.jobStore.tcConfigUrl = localhost:9510
配置
主要配置组件
- 线程池
- JobStore
- DataSources(如有必要)
- 计划程序本身
线程池
quartz线程池的配置,默认如下:
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 10
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
ScheduleFactory
调度工厂类使用一组属性(java.util.Properties)来创建和初始化Quartz Scheduler。
有两个工厂类:
- StdSchedulerFactory
- DirectSchedulerFactory
支持RMI
RMI设置包括调度程序是否应将自身创建为RMI的服务器对象(使其可用于远程连接),要使用的主机和端口等。
Clustering集群
Clustering目前与JDBC-Jobstore(JobStoreTX或JobStoreCMT)和TerracottaJobStore一起使用。功能包括负载平衡和 job故障转移(如果JobDetail的“RequestsRecovery请求恢复”标志设置为true)。
//设置
org.quartz.jobStore.isClustered = true
JTA事务
JobStoreCMT允许在较大的JTA事务中执行Quartz调度操作。开启事务有两种方式
- 通过配置文件
org.quartz.scheduler.wrapJobExecutionInUserTransaction=true
- 通过注释
在job类加注释@ExecuteInJTATransaction
配置
Quartz的配置通常通过使用属性文件(使用StdSchedulerFactory(消耗配置文件并实例化调度程序))来完成。默认情况下,StdSchedulerFactory从“当前工作目录”加载名为“quartz.properties”的属性文件。如果失败,则加载org / quartz包中(作为资源)的“quartz.properties”文件。如果您希望使用除这些默认值之外的文件,则必须定义系统属性“org.quartz.properties”以指向所需的文件。
1. ThreadPool设置
2.配置Global Listeners
org.quartz.triggerListener.NAME.class = com.foo.MyListenerClass
org.quartz.triggerListener.NAME.propName = propValue
org.quartz.triggerListener.NAME.prop2Name = prop2Value
3. 插件配置
org.quartz.plugin.NAME.class = com.foo.MyPluginClass
org.quartz.plugin.NAME.propName = propValue
org.quartz.plugin.NAME.prop2Name = prop2Value
4. RMI设置
5.配置RAMJobStore、配置JDBC-JobStoreTX、配置JDBC-JobStoreCMT、配置DataSources
DataSources可以通过三种方式进行配置:
- 在quartz.properties文件中指定的所有池属性,以便Quartz可以自己创建DataSource。
- 可以指定应用程序服务器管理的Datasource的JNDI位置,以便Quartz可以使用它。
- 自定义的org.quartz.utils.ConnectionProvider实现。
6.使用JDBC-JobStore配置群集
7.配置TerracottaJobStore
job运行状态
- WAITING:等待
- PAUSED:暂停
- ACQUIRED:正常执行
- BLOCKED:阻塞
- ERROR:错误