> For the complete documentation index, see [llms.txt](https://yangsx95.gitbook.io/notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://yangsx95.gitbook.io/notes/domain-specific/ren-wu-diao-du/quartzscheduler.md).

# QuartzScheduler

官方网站：<http://www.quartz-scheduler.org> Github：<https://github.com/quartz-scheduler/quartz>

Quatz 是一个特性丰富的，开源的任务调度库，它几乎可以嵌入所有的 Java 程序，从很小的独立应用程序到大型商业系统。Quartz 可以用来创建成百上千的简单的或者复杂的任务，这些任务可以用来执行任何程序可以做的事情。Quartz 拥有很多企业级的特性，包括支持 JTA 事务和集群。

Quartz 是一个老牌的任务调度系统，98 年构思，01 年发布到 sourceforge。现在更新比较慢，因为已经非常成熟了。Quartz 的目的就是让任务调度更加简单，开发人员只需要关注业务即可。他是用 Java 语言编写的（也有.NET 的版本）。Java 代码能做的任何事情，Quartz 都可以调度。

**特点：**

1. 精确到毫秒级别的调度
2. 可以独立运行，也可以集成到容器中
3. 支持事务（JobStoreCMT ）
4. 支持集群
5. 支持持久化

## Quartz的基本使用

引入依赖：

```xml
<dependency> 
    <groupId>org.quartz-scheduler</groupId> 
    <artifactId>quartz</artifactId> 
    <version>2.3.0</version> 
</dependency>
```

编写代码：

```java
// 创建调度器，用于调度任务，调度器内部拥有一个任务计划表，调度器在这个表里面对各个job任务进行时间分配
SchedulerFactory sfact = new StdSchedulerFactory();
Scheduler schedule = sfact.getScheduler();
// 创建TestJob，用于定义调度程序具体执行的工作内容
public class TestJob implements Job{

    public void execute(JobExecutionContext arg0) throws JobExecutionException {
            
            Date date=new Date();
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.print("now:"+sf.format(date));

    }
}
// 创建JobDetail的实例，对job进行进一步封装，增加一些原信息，比如name和group；还可以传一些kv参数给job
JobDetail jobDetail1 = JobBuilder.newJob((Class<? extends Job>) TestJob.class) //定义Job类为TestJob类
                .withIdentity("myjob1", "group1") //定义name、group
                .build();
// 创建触发器，触发器是一个时间规则
CronTrigger trigger1 =(CronTrigger) TriggerBuilder.newTrigger()
                .withIdentity("trigger1", "group1")
                .withSchedule(CronScheduleBuilder.cronSchedule("0 0 10 ? * MON")) //每周一造成10点执行
                .build();
// 给调度器的计划表增加一条计划，让jobDetail1在trigger1时间点运行任务
schedule.scheduleJob(jobDetail1, trigger1);

// 启动调度器开始执行任务
schedule.start();
```

## Quartz的体系结构

![图 1](/files/vd2yndqiE5A3m1WQNif5)

### Trigger

触发器是用于触发任务的时间规则，`Trigger`类使用`TriggerBuilder`构建，Trigger 接口在 Quartz 有 4 个继承的子接口：

| **子接口**                  | **描述**          | **特点**                                                   |
| ------------------------ | --------------- | -------------------------------------------------------- |
| SimpleTrigger            | 简单触发器           | 固定时刻或时间间隔，毫秒                                             |
| CalendarIntervalTrigger  | 基于日历的触发器        | 比简单触发器更多时间单位，支持非固定时间的触发，例如一年可能 365/366，一个月可能 28/29/30/31 |
| DailyTimeIntervalTrigger | 基于日期的触发器        | 每天的某个时间                                                  |
| CronTrigger              | 基于 Cron 表达式的触发器 |                                                          |

### JobDetail

`JobDetail`代表一个具体的任务，他由`JobBuilder`构建。`JobBuilder`使用关联对象`Job`（任务模板）以及`JobDataMap` 模板参数，具体构建一个任务对象。

### Scheduler

调度器由`SchedulerFactory`创建，创建出的调度器都是单例的。调度器调度任务需要两个对象：`JobDetail`和`Trigger`，调度器会在对应的时间点执行任务。

Scheduler中的方法主要分为三大类：

1. 操作调度器本身，例如调度器的启动`start()`、调度器的关闭`shutdown()`。
2. 操作Trigger，例如`pauseTriggers()`、`resumeTrigger()`。
3. 操作Job，例如`scheduleJob()`、`unscheduleJob()`、`rescheduleJob()`

### Listener

`Listener`是用于监听任务生命周期的监听器。他通过观察者模式，监听`Scheduler`、`Trigger`、`JobDeatil`。

通常使用`Listener`监听任务的执行状态，然后做出相关的业务操作或者通知。

#### TriggerListener

| 方法                 | 作用或执行实际                                                                                                                  |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------ |
| getName()          | 返回监听器的名称                                                                                                                 |
| triggerFired()     | Trigger 被触发，Job 上的 execute() 方法将要被执行时，Scheduler 就调用这个方法                                                                  |
| vetoJobExecution() | 在 Trigger 触发后，Job 将要被执行时由 Scheduler 调用这个方法。TriggerListener 给了一个选择去否决 Job 的执行。假如这个方法返回 true，这个 Job 将不会为此次 Trigger 触发而得到执行 |
| triggerMisfired()  | Trigger 错过触发时调用                                                                                                          |
| triggerComplete()  | Trigger 被触发并且完成了 Job 的执行时，Scheduler 调用这个方法                                                                               |

#### JobListener

#### SchedulerListener

### JobStore

#### RAMJobStore

#### JDBCJobStore

## Quartz的配置文件

`org.quartz.core` 包下，有一个默认的配置文件，`quartz.properties`。当我们没有定义一个同名的配置文件的时候，就会使用默认配置文件里面的配置，他的默认配置如下：

```properties
org.quartz.scheduler.instanceName: DefaultQuartzScheduler 
org.quartz.scheduler.rmi.export: false 
org.quartz.scheduler.rmi.proxy: false 
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false 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.misfireThreshold: 60000 
org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
```

如果要修改上述中的配置，可以在`resource`下，建立一个同包名，同文件名的配置文件，以覆盖默认的配置。
