# 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`下，建立一个同包名，同文件名的配置文件，以覆盖默认的配置。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://yangsx95.gitbook.io/notes/domain-specific/ren-wu-diao-du/quartzscheduler.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
