Quartz定时任务
Quartz是一个开源的Java作业调度框架,支持基于时间间隔的任务调度。其核心组件包括Job(定义任务)、JobDetail(任务详情)、Trigger(触发器)和Scheduler(调度器)。通过SimpleTrigger或CronTrigger可灵活配置执行频率,支持参数传递和持久化存储。示例展示了如何创建每5秒执行的任务,并介绍了Spring Boot集成方案。Quartz还提供监听器接口
一、前言
Quartz定时任务框架。Quartz是一个开源的作业调度框架,它允许开发人员根据时间间隔来调度作业。它实现了作业和触发器的多对多关系,还能将多个作业与不同的触发器关联。Quartz的核心是调度器,由它来调度作业。
二、Quartz的主要组成部分
-
Job(作业):这是一个接口,只有一个方法void execute(JobExecutionContext context),开发者实现这个接口来定义需要执行的任务。
-
JobDetail(作业详情):用来定义Job的实例,包含Job的具体信息,比如Job的类名、组名、以及需要传递的数据等。
-
Trigger(触发器):用于触发Job的执行。它定义了什么时候执行Job,以及执行的频率。有两种主要的触发器:SimpleTrigger(简单触发器)和CronTrigger(基于Cron表达式的触发器)。
-
Scheduler(调度器):是Quartz的核心,负责调度Job和Trigger。它从Trigger获取即将要执行的任务,然后执行Job的execute方法。
使用Quartz的一般步骤:
-
引入Quartz的依赖(如果是Maven项目,则添加依赖)。
-
创建一个实现Job接口的类,重写execute方法,在这里面写需要定时执行的任务。
-
创建JobDetail实例,并指定执行的Job类。
-
创建Trigger实例,指定触发时间和频率。
-
创建Scheduler实例,将JobDetail和Trigger注册到Scheduler中,并启动Scheduler。
下面是一个简单的示例,演示如何使用Quartz每隔5秒执行一次任务。
注意:由于Quartz 2.0之后API有变化,我们使用最新的API。
首先,添加Maven依赖(以Quartz 2.3.2为例):
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
然后,编写一个Job类:
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class SimpleJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("Hello Quartz! " + new java.util.Date());
}
}
接着,编写调度代码:
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
public class QuartzTest {
public static void main(String[] args) throws SchedulerException {
// 1. 创建调度器Scheduler
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
// 2. 创建JobDetail实例,并与SimpleJob类绑定
JobDetail jobDetail = JobBuilder.newJob(SimpleJob.class)
.withIdentity("job1", "group1")
.build();
// 3. 创建Trigger实例,每隔5秒重复执行一次
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(5)
.repeatForever())
.build();
// 4. 将JobDetail和Trigger注册到Scheduler中,并启动
scheduler.scheduleJob(jobDetail, trigger);
scheduler.start();
}
}
除了SimpleTrigger,还可以使用CronTrigger,它基于Cron表达式,可以更灵活地定义时间表。例如,每天中午12点执行一次:
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger2", "group1")
.withSchedule(CronScheduleBuilder.cronSchedule("0 0 12 * * ?"))
.build();
注意:在实际项目中,我们通常会将Scheduler配置为Spring的Bean,使用Spring集成的Quartz来管理,这样更方便。但是上面的例子是独立的Quartz应用。
另外,Quartz还支持持久化作业存储(JobStore),可以将作业和触发器信息存储在数据库中,从而支持集群和故障恢复。
三、核心概念
1. 主要组件
// Job - 定义要执行的任务
public class MyJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("任务执行时间: " + new Date());
}
}
// JobDetail - 任务详情
// Trigger - 触发器,定义执行时间
// Scheduler - 调度器,管理任务调度
2. Maven 依赖
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
3. 简单示例
public class QuartzDemo {
public static void main(String[] args) throws SchedulerException {
// 1. 创建调度器
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
// 2. 创建任务详情
JobDetail job = JobBuilder.newJob(MyJob.class)
.withIdentity("myJob", "group1")
.build();
// 3. 创建触发器
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("myTrigger", "group1")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(10) // 每10秒执行一次
.repeatForever())
.build();
// 4. 将任务和触发器注册到调度器
scheduler.scheduleJob(job, trigger);
// 5. 启动调度器
scheduler.start();
}
}
四、触发器类型
1. SimpleTrigger - 简单触发器
// 立即开始,每30秒执行一次,总共执行5次
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(30)
.withRepeatCount(4)) // 重复4次,加上第一次共5次
.build();
// 延迟5秒开始,每1分钟执行一次,无限重复
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger2", "group1")
.startAt(DateBuilder.futureDate(5, DateBuilder.IntervalUnit.SECOND))
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInMinutes(1)
.repeatForever())
.build();
2. CronTrigger - Cron表达式触发器
// 使用Cron表达式
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger3", "group1")
.withSchedule(CronScheduleBuilder.cronSchedule("0 0/5 * * * ?")) // 每5分钟执行
.build();
3.常用Cron表达式
"0 0 12 * * ?" // 每天中午12点
"0 15 10 ? * *" // 每天上午10:15
"0 0/5 14 * * ?" // 每天下午2点到2:55期间,每5分钟
"0 0-5 14 * * ?" // 每天下午2点到2:05期间,每分钟
"0 0/30 8-9 5,20 * ?" // 每月5号和20号的8点到9点,每30分钟
"0 0 9 ? * MON" // 每周一上午9点
五、Job数据传递
1. 向Job传递参数
public class DataJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
JobDataMap dataMap = context.getJobDetail().getJobDataMap();
String name = dataMap.getString("name");
int count = dataMap.getInt("count");
System.out.println("Name: " + name + ", Count: " + count);
}
}
// 设置参数
JobDetail job = JobBuilder.newJob(DataJob.class)
.withIdentity("dataJob", "group1")
.usingJobData("name", "QuartzJob")
.usingJobData("count", 1)
.build();
2. 在Job执行期间更新数据
public class UpdateDataJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
JobDataMap dataMap = context.getJobDetail().getJobDataMap();
int count = dataMap.getInt("count");
count++;
dataMap.put("count", count);
System.out.println("执行次数: " + count);
}
}
六、持久化配置
1. 数据库持久化
创建 quartz.properties 文件:
# 配置数据源
org.quartz.dataSource.myDS.driver = com.mysql.jdbc.Driver
org.quartz.dataSource.myDS.URL = jdbc:mysql://localhost:3306/quartz
org.quartz.dataSource.myDS.user = root
org.quartz.dataSource.myDS.password = password
org.quartz.dataSource.myDS.maxConnections = 30
# 使用JDBC JobStore
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.dataSource = myDS
org.quartz.jobStore.tablePrefix = QRTZ_
七、Spring Boot 集成
1. 添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
2. 配置类
@Configuration
public class QuartzConfig {
@Bean
public JobDetail sampleJobDetail() {
return JobBuilder.newJob(SampleJob.class)
.withIdentity("sampleJob")
.storeDurably()
.build();
}
@Bean
public Trigger sampleJobTrigger() {
SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(30)
.repeatForever();
return TriggerBuilder.newTrigger()
.forJob(sampleJobDetail())
.withIdentity("sampleTrigger")
.withSchedule(scheduleBuilder)
.build();
}
}
3. Spring管理的Job
@Component
public class SpringJob implements Job {
@Autowired
private SomeService someService; // 可以注入Spring Bean
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
someService.doSomething();
}
}
八、监听器
1. Job监听器
public class MyJobListener implements JobListener {
@Override
public String getName() {
return "MyJobListener";
}
@Override
public void jobToBeExecuted(JobExecutionContext context) {
System.out.println("Job即将执行: " + context.getJobDetail().getKey());
}
@Override
public void jobExecutionVetoed(JobExecutionContext context) {
System.out.println("Job执行被否决: " + context.getJobDetail().getKey());
}
@Override
public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
System.out.println("Job执行完成: " + context.getJobDetail().getKey());
}
}
2. 注册监听器
scheduler.getListenerManager().addJobListener(new MyJobListener());
// 优雅关闭
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
try {
scheduler.shutdown(true);
} catch (SchedulerException e) {
e.printStackTrace();
}
}));
九、总结
-
任务幂等性:确保任务可以重复执行而不会产生副作用。
-
异常处理:合理处理任务执行中的异常。
-
集群部署:在生产环境中使用数据库持久化支持集群。
-
监控日志:记录任务执行日志,便于排查问题。
-
资源清理:应用关闭时正确关闭调度器。
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)