定时调度 **依赖**

  1. <dependency>
  2. <groupId>org.quartz-scheduler</groupId>
  3. <artifactId>quartz</artifactId>
  4. <version>2.2.1</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.quartz-scheduler</groupId>
  8. <artifactId>quartz-jobs</artifactId>
  9. <version>2.2.1</version>
  10. </dependency>

1. 核心

  • Job

    void execute(JobExecutionContext context);

  • JobDetail

一个具体的可执行的调度程序,Job 是这个可执行调度程序所要执行的内容,JobDetail 包含了这个任务调度的方案和策略。
JobDetail 定义的是任务数据,而真正的执行逻辑是在 Job 中,设计成 JobDetail + Job 是因为任务执行时并发造成的影响,故 Scheduler 每次执行都会根据 JobDetail 创建一个新的 Job 实例,避免了并发访问的问题。

  • Trigger

调度参数的配置,调度时间。trigger 共性, startTimeendTime 指定 Trigger 被触发的区间。
Priority 优先级,作用:多个Trigger在同一时刻触发,设置优先级高的任务先执行,优先级 默认5设置成负数是变为默认值,优先级取值区间为 [1-10]

  • SimpleTrigger

从某一时间开始,以一定的时间间隔执行任务,时间间隔为毫秒。

  • **CalendarIntervalTrigger**

时间间隔为月。

  • **DailyTimeIntervalTrigger**

指定每天某个时间段内,以一定时间间隔执行任务,支持指定星期。

startTimeOfDay 每天开始的时间
endTimeOfDay 每天结束的时间
dayOfWeak 需要执行的星期
onDayOfTheWeak 一周中星期几执行
interval 执行时间间隔
intervalUnit 执行间隔的时间单位
repeatCount 重复次数

  • **CronTrigger**

corn表达式定义执行时间间隔。

  • Scheduler

调度容器,一个调度容器中可以注册多个 JobDetailTrigger ,其组合可被 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** 集群实现。
  • **TerracottaJobStore**

    1.2. SchedulerFactory

    创建 Scheduler 提供两个实现:

  • DirectSchedulerFactory 在代码里定制 Scheduler 参数

  • StdSchdulerFactory 直接读取 classpathquartz.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 实现。 JobDetailTrigger 都有 namegroup ,相当于 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

定义任务

  1. 创建 Job 实现类,实现业务逻辑。
  2. 定义 JobDetail,引用这个类。
  3. 加入 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