定时任务框架Quartz详解-基础篇
原创: 蜗牛 Java架构师之路 前天
原文地址
概述
Quartz 是 OpenSymphony 开源组织的一个开源项目,定时任务框架,纯 Java 语言实现,最新版本为 2.3.0。
Quartz 中用到的设计模式:
- Builder 模式
- Factory 模式
- 组件模式
- 链式模式
Quartz 组成部分
- 调度器:scheduler
- 任务:JobDetail
- 触发器:Trigger, 包括 SimpleTrigger 和 CronTrigger
第一个 Quartz 程序
实现每隔 1 秒打印一个 Hello World
1. 创建 Maven 项目,添加依赖:
<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
2. 创建 HelloWorldJob 类
package quartz;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* created by Java-Road
* created in 2018/5/26
*/
public class HelloWorldJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
String strTime = new SimpleDateFormat("HH-mm-ss").format(new Date());
System.out.println( strTime + ":Hello World!");
}
}
3. 创建 MyScheduler 类
package quartz;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
/**
* created by Java-Road
* created in 2018/5/26
*/
public class MyScheduler {
public static void main(String[] args) throws SchedulerException {
//创建调度器Schedule
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
//创建JobDetail实例,并与HelloWordlJob类绑定
JobDetail jobDetail = JobBuilder.newJob(HelloWorldJob.class).withIdentity("job1", "jobGroup1")
.build();
//创建触发器Trigger实例(立即执行,每隔1S执行一次)
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "triggerGroup1")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever())
.build();
//开始执行
scheduler.scheduleJob(jobDetail, trigger);
scheduler.start();
}
}
Quartz 中几个重要的对象
1.Job 和 JobDetail
Job 是 Quartz 中的一个接口,接口下只有 execute 方法,在这个方法中编写业务逻辑。
该接口的源码:
package org.quartz;
public interface Job {
void execute(JobExecutionContext var1) throws JobExecutionException;
}
每次调度执行 Job 时,调用 execute 方法前会创建一个新的 Job 实例,执行完后,关联的 Job 对象实例会被释放,随后 jvm 执行 GC。
JobDetail 是用来绑定 Job,为 Job 实例提供了许多属性,以及 JobDataMap 成员变量属性。调度器 scheduler 通过 JobDetail 对象来添加 Job 实例。
属性:
- name
- group
- jobClass
- jobDataMap
2.JobExecutionContext
当调度器 Scheduler 调用一个 Job 时,就会将 JobExecutionContext 传递给 Job 的 execute() 方法,Job 能通过 JobExecutionContext 对象访问到 Quartz 运行时的环境以及 Job 本身的详细数据信息。
代码演示:
public class HelloWorldJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
String strTime = new SimpleDateFormat("HH-mm-ss").format(new Date());
System.out.println( strTime + ":Hello World!");
System.out.println("JobDetail'name:" + jobExecutionContext.getJobDetail().getKey().getName());
System.out.println("JobDetail'group:" + jobExecutionContext.getJobDetail().getKey().getGroup());
System.out.println("JobDetail'class:" + jobExecutionContext.getJobDetail().getClass());
}
}
3.JobDataMap
任务调度时可以通过 JobExecutionContext 获取 JobDataMap,可以装在任何可序列化的数据对象,JobDataMap 实现了 JDK 的 Map 接口,可以以 Key-Value 的形式存储数据。
实战:JobDetail 和 Trigger 传递数据,HelloWorldJob 类 execute 三种方式获取数据。
//创建JobDetail实例,并与HelloWordlJob类绑定
JobDetail jobDetail = JobBuilder.newJob(HelloWorldJob.class).withIdentity("job1", "jobGroup1")
.usingJobData("key1","this is jobDetail")
.build();
//创建触发器Trigger实例(立即执行,每隔1S执行一次)
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "triggerGroup1")
.usingJobData("key2", "this is trigger")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever())
.build();
HelloWorldJob 获取数据:
public class HelloWorldJob implements Job {
private String key1;
private String key2;
public String getKey1() {
return key1;
}
public void setKey1(String key1) {
this.key1 = key1;
}
public String getKey2() {
return key2;
}
public void setKey2(String key2) {
this.key2 = key2;
}
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
String strTime = new SimpleDateFormat("HH-mm-ss").format(new Date());
System.out.println( strTime + ":Hello World!");
//获取DataMap数据方法一
System.out.println("JobDetail JobDataMap:" + jobExecutionContext.getJobDetail().getJobDataMap().get("key1"));
System.out.println("Trigger JobDataMap:" + jobExecutionContext.getTrigger().getJobDataMap().get("key2"));
//获取DataMap数据方法二
System.out.println("JobDataMap:" + jobExecutionContext.getMergedJobDataMap().get("key1"));
System.out.println("JobDataMap:" + jobExecutionContext.getMergedJobDataMap().get("key2"));
//获取数据方法三
System.out.println("通过成员变量获取" + key1);
System.out.println("通过成员变量获取" + key2);
}
}
4.Trigger
Trigger 是 Quartz 中的触发器,任务执行时会通知调度器 Scheduler 何时触发,几个重要的属性。
- Jobkey:表示 job 实例的标识
- StartTime:表示触发器首次被触发的时间 (Java.util.Date)。
- EndTime:表示触发器结束触发的时间 (Java.util.Date)
实战:实现 5S 后执行,10S 后结束,期间每隔 1S 执行一次定时任务
代码演示:
MyScheduler 类
public class MyScheduler {
public static void main(String[] args) throws SchedulerException {
//创建调度器Schedule
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
//创建JobDetail实例,并与HelloWordlJob类绑定
JobDetail jobDetail = JobBuilder.newJob(HelloWorldJob.class).withIdentity("job1", "jobGroup1")
.build();
//创建触发器Trigger实例(5S后执行,10S后结束)
//开始时间(5S后)
Date date1 = new Date();
date1.setTime(date1.getTime() + 5000);
//结束时间(10S后)
Date date2 = new Date();
date2.setTime(date2.getTime() + 10000);
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "triggerGroup1")
.startAt(date1)
.endAt(date2)
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever())
.build();
//开始执行
scheduler.scheduleJob(jobDetail, trigger);
scheduler.start();
}
}
5.SimpleTrigger
SimpleTrigger 可以实现在一个指定时间段内执行一次作业任务或一个时间段内多次执行作业任务。
实战:5S 后开始执行,间隔时间为 1S,第一次执行后连续执行 3 次
package quartz2;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import java.util.Date;
/**
* created by Java-Road
* created in 2018/5/27
*/
public class MyScheduler2 {
public static void main(String[] args) throws SchedulerException {
//创建调度器Schedule
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
//创建JobDetail实例,并与HelloWordlJob类绑定
JobDetail jobDetail = JobBuilder.newJob(HelloWorldJob.class).withIdentity("job1", "jobGroup1")
.build();
//创建触发器Trigger实例(5S后执行,一直执行)
//开始时间(5S后)
Date date1 = new Date();
date1.setTime(date1.getTime() + 5000);
SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger()
.withIdentity("trigger1", "triggerGroup1")
.startAt(date1)
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1)
.withRepeatCount(3))
.build();
//开始执行
scheduler.scheduleJob(jobDetail, trigger);
scheduler.start();
}
}
6.CronTrigger
CronTrigger 功能非常强大,是基于日历的作业调度,而 SimpleTrigger 是精准指定间隔,所以相比 SimpleTrigger,CroTrigger 更加常用。CroTrigger 是基于 Cron 表达式的,先了解下 Cron 表达式:
由 7 个子表达式组成字符串的,格式如下:
[秒] [分] [小时] [日] [月] [周] [年]
Cron 表达式的语法就不多说了,因为我也记不住只能度娘,给大家提供个在线生成 Cron 表达式的工具:http://cron.qqe2.com/ ,方便实用。
实战:实现每周一到周五上午 10:30 执行定时任务
package quartz2;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import java.util.Date;
/**
* created by Java-Road
* created in 2018/5/27
*/
public class MyScheduler3 {
public static void main(String[] args) throws SchedulerException {
//创建调度器Schedule
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
//创建JobDetail实例,并与HelloWordlJob类绑定
JobDetail jobDetail = JobBuilder.newJob(HelloWorldJob.class).withIdentity("job1", "jobGroup1")
.build();
//创建触发器CronTrigger实例(每周一到周五10:30执行任务)
CronTrigger trigger = (CronTrigger) TriggerBuilder.newTrigger()
.withIdentity("trigger1", "triggerGroup1")
.startNow()
.withSchedule(CronScheduleBuilder.cronSchedule("* 30 10 ? * 1/5 *"))
.build();
//开始执行
scheduler.scheduleJob(jobDetail, trigger);
scheduler.start();
}
}
Copyright © 2015 Powered by MWeb, Theme used GitHub CSS.