定时调度
**依赖**
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.1</version>
</dependency>
1. 核心
Job
void execute(JobExecutionContext context);
JobDetail
一个具体的可执行的调度程序,Job 是这个可执行调度程序所要执行的内容,JobDetail 包含了这个任务调度的方案和策略。
JobDetail 定义的是任务数据,而真正的执行逻辑是在 Job 中,设计成 JobDetail + Job
是因为任务执行时并发造成的影响,故 Scheduler
每次执行都会根据 JobDetail
创建一个新的 Job
实例,避免了并发访问的问题。
Trigger
调度参数的配置,调度时间。trigger 共性, startTime
和 endTime
指定 Trigger
被触发的区间。Priority
优先级,作用:多个Trigger在同一时刻触发,设置优先级高的任务先执行,优先级 默认5
,设置成负数是变为默认值,优先级取值区间为 [1-10]
。
SimpleTrigger
从某一时间开始,以一定的时间间隔执行任务,时间间隔为毫秒。
**CalendarIntervalTrigger**
时间间隔为月。
**DailyTimeIntervalTrigger**
指定每天某个时间段内,以一定时间间隔执行任务,支持指定星期。
startTimeOfDay
每天开始的时间endTimeOfDay
每天结束的时间dayOfWeak
需要执行的星期onDayOfTheWeak
一周中星期几执行interval
执行时间间隔intervalUnit
执行间隔的时间单位repeatCount
重复次数
**CronTrigger**
corn表达式定义执行时间间隔。
Scheduler
调度容器,一个调度容器中可以注册多个 JobDetail
和 Trigger
,其组合可被 Scheduler
容器调度。Scheduler
是 Quartz 核心,所有的任务都是有他来创建的。
Calendar
org.quartz.Calendar
补充 Trigger 时间,排除或加入一些特定时间点。HolidayCalendar
特定的日期,精度 天
。DailyCalendar
每日的时间段格式 / HH:MM[:SS[:mmm]],精度 毫秒
。WeeklyCalendar
每个星期的星期几,精度 天
。MontnlyCalendar
每个月的几号,精度 天
。AnnualCalendar
每年的哪天。CronCalendar
corn表达式,最大精度 秒
。
1.1. JobStore
存储运行时信息,包括 Trigger
Scheduler
JobDetail
业务锁
等。他有多种实现:
RAMJob
内存实现。JobStoreTX
JDBC 事务有Quartz管理。JobStoreCMT
JDBC 使用容器事务。**ClusteredJobStrore**
集群实现。-
1.2. SchedulerFactory
创建 Scheduler 提供两个实现:
DirectSchedulerFactory
在代码里定制 Scheduler 参数StdSchdulerFactory
直接读取classpath
下quartz.properties
参数(不存在使用默认值)配置
通常使用 StdSchedulerFactory ,SchedulerFactory 本身支持 RMI stub,可以管理远程 Scheduler,与本地一样,可以远程提交 Job。
DirectSchedulerFactory 创建接口:
public void createScheduler(String schedulerName,String schedulerInstanceId, ThreadPool threadPool, JobStore jobStore) throw SchedulerException;
2. API
2.x
后采用 DSL
( domain-specific language / 领域特定语言),例如: newTrigger
newJob
代码,通过 Builder 实现。 JobDetail
和 Trigger
都有 name
和 group
,相当于 Map<String(name),String(group)>
。 group
为组织单元, Scheduler
提供了一些对整组操作的API。
3. Misfire
错失触发策略
Scheduler资源不足时,或者机器崩溃重启,该触发的事件没有触发,即为 miss fire
。
注:Misfire阀值配置在jobStore,只有超过这个值才算是MisFire,小于这个值都会被重新发送。
SimpleTrigger
继承于 Trigger
,Misfire策略包含:
Trigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY=-1
会在资源合适的时候重新触发所有misFire任务,并且不会影响现有的调度任务时间。SimpleTrigger.MISFIRE_INSTRUCTION_FIRE_NOW=1
忽略已经misFire的任务、立即执行调度,适用于只执行一次的任务。SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT=2
将 startTime 设置为当前时间,立即重新调度任务,包括 Misfire 的任务。SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT=3
功能与上面的基本相同,只是忽略掉 Misfire 的任务。SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT=4
在下一次调度时间点,重新开启调度任务,包括Misfire。SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT=5
同上,只是忽略 Misfire 。Trigger.MISFIRE_INSTRUCTION_SMART_POLICY=0
所有 Trigger 的默认值,将 Misfire 的处理逻辑交由 Quartz 去处理:- MISFIRE_INSTRUCTION_FIRE_NOW 只执行一次的调度。
- MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT 无限次的调度 repeatCount 。
- MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT 其他。
4. JobDetail && Job
定义任务
- 创建 Job 实现类,实现业务逻辑。
- 定义 JobDetail,引用这个类。
- 加入 ScheduleJob。
调度任务
// 1.
JobClass jobClass = JobDetail.getJobClass();
// 2. Job实现类必须有一个public无参的构造方法
Job jobInstance = jobClass.newInstance();
// 3. JobExecutionContext是Job运行的上下文,可以获得Trigger、Scheduler、JobDetail的信息
jobInstance.execute(JobExecutionContext context);
注:每次调度都会创建一个新的Job实例,并发时不存在对临界资源的访问问题,如果需要共享JobDataMap时,还是会存在临界资源的并发访问的问题。
5. JobDataMap
每一个JobDetail都会有一个JobDataMap.
Job方法声明一个和JobDataMap中key值相同的变量利用setter方法注入进来,对于同一个JobDetail实例,执行多个Job实例,是共享同样的JobDateMap,如果在任务中修改了里面的值对其他实例也会有影响。
Job有可能是并发执行的,有时候我们不想并发执行加入 @DisallowConcurrentExecution
解决这个问题。注解对JobDetail实例生效,如果定义两个 JobDetail,引用同一个 Job 类,是可以并发执行的。
6. JobExecutionException
Job.execute()
不允许抛出除 JobExecutionException
以外的任何异常,所有异常都要 try/catch
。
7. 其他属性
Durability
RequestsRecovery
如果一个任务不是正常退出时,机器宕机、断电、不包括抛出异常这种情况。Quartz再次启动时会重新运行这个实例。8. quartz.properties
org.quartz.scheduler.instanceName = DefaultQuartzScheduler org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool org.quartz.threadPool.threadCount = 10 org.quartz.threadPool.threadPriority = 5 org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore