1. 什么是Quartz
Quartz是一个由Java开发的开源定时作业调度框架,就是按照设定,在某一固定时刻或者时间间隔去进行执行某个任务。
Quartz 主要组成部分有:
- 调度器:Scheduler
- 任务:JobDetail,Job
- 触发器:Trigger,包括SimpleTrigger和CronTrigger
下面我们先看一个简单实例:
2. Quartz 简单Demo搭建
(一)maven 配置:
<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
(二) 新建打印不同文字的Job
Job就是我们要定时执行的具体操作
public class PrintJob1 implements Job {
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
String printTime = new SimpleDateFormat("yy-MM-dd HH-mm-ss").format(new Date());
System.out.println("Job1 start at "+printTime + " , print This is Job1");
}
}
public class PrintJob2 implements Job {
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
String printTime = new SimpleDateFormat("yy-MM-dd HH-mm-ss").format(new Date());
System.out.println("Job2 start at "+printTime + " , print This is Job2");
}
}
(三)新建触发器和调度器,分别调用Job1 和Job2
public class MySchedule {
public static void main(String[] args) throws Exception{
// 1、创建调度器Scheduler
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
// 2、创建JobDetail实例,并与PrintWordsJob类绑定(Job执行内容)
JobDetail jobDetail = JobBuilder.newJob(PrintJob1.class)
.withIdentity("job1", "group1").build();
JobDetail jobDetail2 = JobBuilder.newJob(PrintJob2.class)
.withIdentity("job2", "group2").build();;
// 3、构建Job1的Trigger实例,每隔1s执行一次
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")
.startNow()//立即生效
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(1)//每隔1s执行一次
.repeatForever()).build();//一直执行
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("trigger2", "group2")
.usingJobData("trigger2", "这是job2的trigger")
.startNow()//立即生效
.withSchedule(CronScheduleBuilder.cronSchedule("0/6 * * * * ? "))
.build();
//4、执行
scheduler.scheduleJob(jobDetail, trigger);
scheduler.scheduleJob(jobDetail2,cronTrigger);
scheduler.start();
//睡眠
TimeUnit.MINUTES.sleep(1);
scheduler.shutdown();
}
}
该程序执行结果为,Job1直接设置每秒执行一次,Job2使用cron表达式设置每六秒执行一次,执行结果如下:
3. Quartz 基本组成
Quartz模块图如下:
(1) 调度器-Scheduler
Scheduler被用来对Trigger和Job进行管理。Trigger和JobDetail可以注册到Scheduler中,两者在Scheduler中都拥有自己的唯一的组和名称用来进行彼此的区分,Scheduler可以通过组名或者名称来对Trigger和JobDetail来进行管理。
一个Trigger只能对应一个Job,但是一个Job可以对应多个Trigger。每个Scheduler都包含一个SchedulerContext,用来保存Scheduler的上下文。Job和Trigger都可以获取SchedulerContext中的信息。
(2) 触发器-Trigger
Trigger定义了何时触发任务,主要是两种SimpleTrigger和CronTigger,其他Tigger基本都可以通过这两种实现。Trigger还可以定义错过的任务如何处理。
Trigger的的公共属性
- startTime属性:设置trigger第一次触发的时间;该属性的值是java.util.Date类型,表示某个指定的时间点;
- endTime属性:表示trigger失效的时间点。比如,”每月第5天执行”的trigger,如果其endTime是7月1号,则其最后一次执行时间是6月5号。
SimpleTrigger
SimpleTrigger可以满足的调度需求是:在具体的时间点执行一次,或者在具体的时间点执行,并且以指定的间隔重复执行若干次。
比如:可以设置它在2019年1月16日的上午12:0:0准时触发,或者在这个时间点触发,并且每隔2秒触发一次,一共重复10次。
所以,SimTrigger 包括开始时间、结束时间、重复次数以及重复的间隔等属性。
下面是几个基于简单时间点的例子:
- 指定时间开始触发,不重复:
SimpleTrigger trigger = (SimpleTrigger) newTrigger()
.withIdentity("trigger1", "group1")
.startAt(myStartTime) // some Date
.forJob("job1", "group1") // identify job with name, group strings
.build();
指定时间触发,每隔10秒执行一次,重复10次:
trigger = newTrigger()
.withIdentity("trigger3", "group1")
.startAt(myTimeToStartFiring) // if a start time is not given (if this line were omitted), "now" is implied
.withSchedule(simpleSchedule()
.withIntervalInSeconds(10)
.withRepeatCount(10)) // note that 10 repeats will give a total of 11 firings
.forJob(myJob) // identify job with handle to its JobDetail itself
.build();
5分钟以后开始触发,仅执行一次:
trigger = (SimpleTrigger) newTrigger()
.withIdentity("trigger5", "group1")
.startAt(futureDate(5, IntervalUnit.MINUTE)) // use DateBuilder to create a date in the future
.forJob(myJobKey) // identify job with its JobKey
.build();
立即触发,每个5分钟执行一次,直到22:00:
trigger = newTrigger()
.withIdentity("trigger7", "group1")
.withSchedule(simpleSchedule()
.withIntervalInMinutes(5)
.repeatForever())
.endAt(dateOf(22, 0, 0))
.build();
建立一个触发器,将在下一个小时的整点触发,然后每2小时重复一次:
trigger = newTrigger()
.withIdentity("trigger8") // because group is not specified, "trigger8" will be in the default group
.startAt(evenHourDate(null)) // get the next even-hour (minutes and seconds zero ("00:00"))
.withSchedule(simpleSchedule()
.withIntervalInHours(2)
.repeatForever())
// note that in this example, 'forJob(..)' is not called which is valid
// if the trigger is passed to the scheduler along with the job
.build();
scheduler.scheduleJob(trigger, job);
CronTrigger
CronTrigger通常比Simple Trigger更有用,它可以提供基于日历的作业调度。CroTrigger是基于Cron表达式的,Cron表达式格式如下:[秒] [分] [小时] [日] [月] [周] [年]
生成Cron表达式链接
实例:
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("trigger2", "group2")
.usingJobData("trigger2", "这是job2的trigger")
.startNow()//立即生效
.withSchedule(CronScheduleBuilder.cronSchedule("0/6 * * * * ? "))
.build();
(3) Job与JobDetail
Job 接口只有一个方法execute
,表明该job需要完成什么类型的任务。其他的该接口包含的属性等由JobDetail 来完成。
Job实例:
public class PrintJob1 implements Job {
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
String printTime = new SimpleDateFormat("yy-MM-dd HH-mm-ss").format(new Date());
System.out.println("Job1 start at "+printTime + " , print This is Job1");
}
}
JobDetail实例:
JobDetail jobDetail2 = JobBuilder.newJob(PrintJob2.class)
.withIdentity("job2", "group2").build();;