Quartz 定时任务框架介绍
文章目录
一、Quartz 是什么?
Quartz Scheduler 是一个 Java 的“任务调度框架(Job Scheduling Framework)”。
它的核心作用是:
在指定时间、按指定规则,自动执行某些 Java 代码。
Quartz 适合场景:
- 每天凌晨自动对账
- 每5分钟同步一次数据
- 每月1号生成报表
- 延迟30分钟取消未支付订单
- 定时扫描FTP文件
- 自动重试失败任务
- 对账系统
- 财务结算
- 大数据同步
- 定时推送
- 自动重试
- 批量任务
- 分布式定时任务
- T+1清算
- 夜间跑批
- 自动生成账单
- 数据同步
- 30 分钟未支付自动取消
- MQ 失败后的重试机制
它比 Spring Boot 自带的 @Scheduled 更强大、更专业。
二、Quartz 能解决什么问题?
1. 替代简单的 while + sleep
很多初学者会写:
while(true){
doTask();
Thread.sleep(60000);
}
问题:
- 不易管理
- 无法动态修改
- 容易线程泄漏
- 不支持复杂时间表达式
- 不支持失败恢复
Quartz 专门解决这些问题。
2. 支持复杂定时规则
Spring 自带:
@Scheduled(cron = "0 0 1 * * ?")
只能简单定时。
而 Quartz 支持:
- Cron表达式
- 固定间隔
- 指定开始结束时间
- 指定重复次数
- 动态修改时间
- 暂停/恢复任务
3. 持久化任务
Quartz 可以把任务存数据库。
即使:
- 服务重启
- JVM崩溃
- 机器宕机
任务仍然不会丢失。
4. 集群调度
多个服务器同时部署时:
Quartz 可以保证:
一个任务只会被其中一台机器执行。
适合:
- 微服务
- 分布式系统
- 高可用系统
5. 动态管理任务
运行中:
- 新增任务
- 删除任务
- 修改Cron
- 立即执行
不需要重启项目。
三、Quartz 核心概念
Quartz 最重要的几个对象:
| 概念 | 作用 |
|---|---|
| Job | 真正执行的任务 |
| JobDetail | Job 的描述信息 |
| Trigger | 触发规则 |
| Scheduler | 调度器 |
执行流程:
Scheduler
↓
Trigger(什么时候执行)
↓
JobDetail
↓
Job(调用 execute() 执行具体逻辑)
四、Quartz 和 Spring @Scheduled 区别
| 对比 | Quartz | @Scheduled |
|---|---|---|
| 简单程度 | 较复杂 | 非常简单 |
| 动态修改 | 支持 | 不支持 |
| 持久化 | 支持 | 不支持 |
| 集群 | 支持 | 不支持 |
| 失败恢复 | 支持 | 不支持 |
| 数据库存储 | 支持 | 不支持 |
| 适合企业级 | 是 | 一般简单任务 |
五、引入 Quartz
如果你想使用 jdk8 并且没有使用 springboot 框架,Maven依赖:
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<!-- 2.4.1 是支持jdk8的最后一个版本-->
<version>2.4.1</version>
<scope>compile</scope>
</dependency>
如果你使用 spring boot 框架,Maven依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
六、Quartz 使用示例
1.普通使用(非SpringBoot)
第一步:创建 Job
Job 就是真正执行的任务。
import org.quartz.Job;
import org.quartz.JobExecutionContext;
public class HelloJob implements Job {
@Override
public void execute(JobExecutionContext context) {
System.out.println("Hello Quartz:" + new java.util.Date());
}
}
第二步:创建 Scheduler
package demo;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
public class QuartzDemo {
public static void main(String[] args) throws Exception {
// 1. 创建 JobDetail
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
.withIdentity("helloJob")
.build();
// 2. 创建 Trigger
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("helloTrigger")
.startNow()
//每隔5秒执行一次
.withSchedule(
SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(5)
.repeatForever()
)
.build();
// 3. 获取 Scheduler
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
// 4. 注册任务和触发器
scheduler.scheduleJob(jobDetail, trigger);
// 5. 启动调度器
scheduler.start();
}
}
运行效果:
Hello Quartz:Sat May 24 10:00:00
Hello Quartz:Sat May 24 10:00:05
Hello Quartz:Sat May 24 10:00:10
2.springboot中使用
第一步:创建 Job
@Component
public class HelloJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context) {
System.out.println("处理订单");
}
}
第一步:创建配置类
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class QuartzConfig {
/**
* 定义Job
*/
@Bean
public JobDetail helloJobDetail() {
return JobBuilder.newJob(HelloJob.class)
.withIdentity("helloJob")
.storeDurably()
.build();
}
/**
* 定义触发器
*/
@Bean
public Trigger helloTrigger() {
SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
//每个5秒执行一次
.withIntervalInSeconds(5)
.repeatForever();
return TriggerBuilder.newTrigger()
.forJob(helloJobDetail())
.withIdentity("helloTrigger")
.withSchedule(scheduleBuilder)
.build();
}
}
七、Cron 表达式
Quartz 最常用的是 Cron。
1.常见 Cron 示例
| 表达式 | 含义 |
|---|---|
0/5 * * * * ? | 每5秒 |
0 0/1 * * * ? | 每1分钟 |
0 0 1 * * ? | 每天1点 |
0 0 1 1 * ? | 每月1号1点 |
0 0 9 ? * MON | 每周一9点 |
0 0,2,4 13 * * ? | 每天的 13:00、13:02、13:04 分别执行一次 |
2.Quartz Cron 和 Linux Cron 区别
Quartz 多一位“秒”。
Linux:
分 时 日 月 周
Quartz:
秒 分 时 日 月 周 年(可选)
3.CronTrigger 使用 Cron 示例
@Bean
public Trigger cronTrigger() {
//每10秒执行一次
CronScheduleBuilder cron = CronScheduleBuilder.cronSchedule("0/10 * * * * ?");
return TriggerBuilder.newTrigger()
.forJob(helloJobDetail())
.withIdentity("cronTrigger")
.withSchedule(cron)
.build();
}
八、Quartz 常用 API
1.JobBuilder
创建任务。
JobBuilder.newJob(HelloJob.class)
2.TriggerBuilder
创建触发器。
TriggerBuilder.newTrigger()
3.SimpleScheduleBuilder
简单周期任务。
.withIntervalInSeconds(5)
.repeatForever()
4.CronScheduleBuilder
Cron 定时规则。
cronSchedule("0 0 12 * * ?")
5.JobDataMap(传递参数)
Quartz 支持给任务传参。
设置参数
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
.usingJobData("name", "Tom")
.build();
获取参数
非 springboot 框架:
import org.quartz.Job;
import org.quartz.JobExecutionContext;
public class HelloJob implements Job {
@Override
public void execute(JobExecutionContext context) {
//获取 JobDetail 中的参数
JobDataMap map = context.getMergedJobDataMap();
String name = map.getString("name");
System.out.println("Hello Quartz:" + name);
}
}
springboot 框架:
@Component
public class HelloJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context) {
//获取 JobDetail 中的参数
JobDataMap map = context.getMergedJobDataMap();
String name = map.getString("name");
System.out.println("Hello Quartz:" + name);
}
}
九、动态创建任务(常用)
企业里经常:
- 数据库存cron
- 页面动态新增任务
- 用户自定义任务
这种不能写死 @Bean。
需要动态操作:
1.动态新增任务
@Autowired
private Scheduler scheduler;
public void addJob() throws Exception {
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
.withIdentity("job1", "group1")
.build();
CronTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")
.withSchedule(
CronScheduleBuilder
.cronSchedule("0/5 * * * * ?")
)
.build();
scheduler.scheduleJob(jobDetail, trigger);
}
2.删除任务
scheduler.deleteJob(
JobKey.jobKey("job1", "group1")
);
3.暂停任务
scheduler.pauseJob(
JobKey.jobKey("job1", "group1")
);
4.恢复任务
scheduler.resumeJob(
JobKey.jobKey("job1", "group1")
);
5.修改Cron
TriggerKey triggerKey =
TriggerKey.triggerKey("trigger1", "group1");
CronTrigger trigger =
TriggerBuilder.newTrigger()
.withIdentity(triggerKey)
.withSchedule(
CronScheduleBuilder
.cronSchedule("0/30 * * * * ?")
)
.build();
scheduler.rescheduleJob(triggerKey, trigger);
十、Quartz 持久化(重要)
默认 Quartz 是内存模式。
重启后任务丢失。
企业通常使用:
MySQL + Quartz JDBC JobStore
任务会存数据库。
1.application.yml
spring:
quartz:
job-store-type: jdbc
jdbc:
initialize-schema: always
2.Quartz 表结构
Quartz 会自动创建:
QRTZ_JOB_DETAILS
QRTZ_TRIGGERS
QRTZ_CRON_TRIGGERS
QRTZ_FIRED_TRIGGERS
...
大约十几张表。
十一、Quartz 集群与线程池(重点)
多个服务实例:
A服务器
B服务器
C服务器
Quartz 集群可保证:
同一任务不会重复执行
只会:
A执行
B/C等待
1.集群配置
spring:
quartz:
properties:
org:
quartz:
scheduler:
instanceName: clusteredScheduler
jobStore:
isClustered: true
2.Quartz 线程池
Quartz 自己维护线程池。
spring:
quartz:
properties:
org:
quartz:
threadPool:
threadCount: 10
表示:
同时最多10个任务并发执行
十二、Quartz 防止任务并发执行
默认:
同一个 Job 可能并发执行。
例如:
任务执行10秒
但cron每5秒触发
会导致:
多个任务同时执行
解决:
@DisallowConcurrentExecution
public class HelloJob implements Job {
}
十三、Quartz 缺点和常见问题
1.缺点
| 问题 | 说明 |
|---|---|
| 配置复杂 | 比 @Scheduled 重 |
| 学习成本较高 | 概念较多 |
| 集群依赖数据库 | 配置麻烦 |
| 大规模任务性能一般 | 超大规模需专门调度平台 |
2.常见问题
(1). 任务重复执行
原因:
多节点部署但没开启集群。
(2). Job 并发问题
解决:
@DisallowConcurrentExecution
(3). 任务阻塞
原因:
Quartz线程池太小。
(4). 数据库锁竞争
Quartz 集群本质依赖数据库锁。
高并发任务过多时:
可能有锁竞争。
十四、现在企业里还有哪些替代方案?
除了 Quartz:
| 框架 | 特点 |
|---|---|
| XXL-Job | 国内最流行 |
| Elastic-Job | 分布式 |
| PowerJob | 新一代 |
| SchedulerX | 阿里云 |
| Spring Scheduled | 简单轻量 |
企业里现在最常用的是?
国内互联网:
- XXL-Job 很多
- Quartz 也非常多
- Spring Scheduled 最基础
银行、证券、传统企业:
Quartz 仍然大量存在。
因为:
- 稳定
- 成熟
- 历史悠久
- 功能完整
十五、推荐学习路线
第一阶段
先掌握:
- Job
- Trigger
- Cron
- Scheduler
第二阶段
学习:
- 动态任务
- Job参数
- 并发控制
第三阶段(重点)
学习:
- JDBC持久化
- 集群模式
- 分布式任务
第四阶段
再学习:
- XXL-Job
- Elastic-Job
- PowerJob
更多推荐
所有评论(0)