一、基本介绍
Quartz概要
- OpenSymphony提供的强大的开源任务调度框架;
- 官网:http://www.quartz-scheduler.org;
- 纯Java实现,精细控制排程。
Quartz特点
- 第一个特点就是他强大的调度功能,那作为Spring默认的调度框架,Quartz很容易与Spring集成,实现灵活可配置的调度功能,还提供了调度运行环境的持久化机制,
可以保存并恢复调度现场
,即使系统因故障关闭,任务调度现场数据并不会丢失,那Timer就做不到这点啦,Timer一旦执行失败,接下来的任务也不能执行了,并且他的一切的信息都会丢失; - 第二个特点是灵活的运用方式,允许开发人员灵活的定义触发器的调度时间表并可以对触发器和任务进行关联映射,Quartz提供了组件式的监听器,各种插件,线程池等功能,支持任务和调度的多种组合方式,支持调度数据的多种存储方式;
- 第三个特点是分布式和集群能力,当然,这不是我们本门课程的内容,有兴趣的同学呢,可以自行查找相关资料了解。
Quartz的设计模式
- Builder模式;
- Factory模式;
- 组件模式;
- 链式写法;
Quartz三个核心概念
- 调度器;
- 任务;
- 触发器。
Quartz体系结构
- JobDetail:它包含了任务的实现类和这个类的一些信息。
- trigger:触发器,可以决定任务什么时候被调用。
- SimpleTrigger:可以执行类似Timer的一些操作,比如说,定频率的执行某一个task。
- CronTrigger:能实现更复杂的一些业务逻辑,比如说,task每周执行一次。
- scheduler:调度器,定时定频率的执行JobDetail,通过schedule将JobDetail和trigger绑定在了一起。
- start
- stop
- pause
- resume
Quartz重要组成
- Job:接口,只有一个方法(void execute(JobExecutionContext context)),开发人员可以实现这个接口,定义运行任务,这个方法相当于TimerTask下的run方法,区别是它有一个参数(JobExecutionContext ),这个参数提供了调度上下文的各种信息,Job运行时的信息就保存在JobExecutionContext 里JobDataMap实例中。
- JobDetail:Quartz在每次执行Job时都重新创建一个Job实例,所以它不直接接受一个Job实例,相反,它接受一个Job实现类,以便运行时通过newInstence的反射机制实例化Job,因此,需要一个类来描述Job的实现类及其他相关的静态信息,如Job的名字,描述,关联的监听器等信息,JobDetail就承担了这样的一个角色。
- JobBuilder:用来定义或创建JobDetail的实例。
- JobStore:接口,用来保存Job数据的,实现类主要有:RAMJobStore,JobStoreTX,JobStoreCMT。JobStoreTX和JobStoreCMT均将数据保存在数据库中,RAMJobStore将数据保存在内存中。
- Trigger:类,描述触发Job执行的时间和触发规则。主要有SimpleTrigger和CronTrigger两个子类。
- TriggerBuilder:用来定义或创建触发器的实例。
- ThreadPool:Schedule使用这个线程池作为任务运行的基础设施,任务通过共享线程池中线程提高运行的效率,可以解决并发的问题。
- Scheduler:代表Quartz的一个独立运行容器,Trigger和JobDetail可以注射到Schedule容器中。
- Calendar:一个Trigger可以和多个Calendar关联,以排除或包含某些时间点。
- 监听器
- JobListener
- TriggerListener
- SchedulerListener
二、第一个Quartz程序
让任务每隔两秒打印一次hellworld
任务类
package helloquartz.one;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
/**
* 编写 自定义任务
*/
public class HelloJob implements Job{
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
// 打印当前的执行时间,格式为2017-01-01 00:00:00
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("Current Exec Time Is : " + sf.format(date));
// 编写具体的业务逻辑
System.out.println("Hello World!");
}
}
任务调度类
package helloquartz.one;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
/**
* 编写 任务调度类
*/
public class HelloScheduler {
public static void main(String[] args) throws SchedulerException {
// 创建一个 JobDetail 实例,将该实例与 HelloJob 实例绑定
JobDetail jobDeatil = JobBuilder.newJob(HelloJob.class)
.withIdentity("myjob", "jobgroup1")// 定义标识符
.build();
System.out.println("--------jobDetail's name : " + jobDeatil.getKey().getName());
System.out.println("--------jobDetail's group : " + jobDeatil.getKey().getGroup());
System.out.println("--------jobDetail's jobClass : " + jobDeatil.getJobClass().getName());
// 创建一个 Trigger 实例,定义该 job 立即执行,并且每隔两秒重复执行一次,直到永远
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("myTrigger","trigroup1")// 定义标识符
.startNow()// 定义立即执行
.withSchedule(SimpleScheduleBuilder
.simpleSchedule()
.withIntervalInSeconds(2)
.repeatForever())// 定义执行频度
.build();
// 创建 Scheduler 实例
SchedulerFactory sfact = new StdSchedulerFactory();
Scheduler scheduler = sfact.getScheduler();
// 绑定 JobDetail 和 trigger
scheduler.scheduleJob(jobDeatil, trigger);
// 执行任务
scheduler.start();
// 打印当前的执行时间,格式为2017-01-01 00:00:00
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("--------Current Time Is : " + sf.format(date));
}
}
运行结果
--------jobDetail's name : myjob
--------jobDetail's group : jobgroup1
--------jobDetail's jobClass : helloquartz.one.HelloJob
2018-03-06 19:08:51,340 [INFO ][main] Using default implementation for ThreadExecutor (org.quartz.impl.StdSchedulerFactory:StdSchedulerFactory.java:1172)
2018-03-06 19:08:51,394 [INFO ][main] Job execution threads will use class loader of thread: main (org.quartz.simpl.SimpleThreadPool:SimpleThreadPool.java:268)
2018-03-06 19:08:51,415 [INFO ][main] Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl (org.quartz.core.SchedulerSignalerImpl:SchedulerSignalerImpl.java:61)
2018-03-06 19:08:51,415 [INFO ][main] Quartz Scheduler v.2.2.3 created. (org.quartz.core.QuartzScheduler:QuartzScheduler.java:240)
2018-03-06 19:08:51,416 [INFO ][main] RAMJobStore initialized. (org.quartz.simpl.RAMJobStore:RAMJobStore.java:155)
2018-03-06 19:08:51,417 [INFO ][main] Scheduler meta-data: Quartz Scheduler (v2.2.3) 'DefaultQuartzScheduler' with instanceId 'NON_CLUSTERED'
Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
NOT STARTED.
Currently in standby mode.
Number of jobs executed: 0
Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.
(org.quartz.core.QuartzScheduler:QuartzScheduler.java:305)
2018-03-06 19:08:51,417 [INFO ][main] Quartz scheduler 'DefaultQuartzScheduler' initialized from default resource file in Quartz package: 'quartz.properties' (org.quartz.impl.StdSchedulerFactory:StdSchedulerFactory.java:1327)
2018-03-06 19:08:51,417 [INFO ][main] Quartz scheduler version: 2.2.3 (org.quartz.impl.StdSchedulerFactory:StdSchedulerFactory.java:1331)
2018-03-06 19:08:51,418 [INFO ][main] Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started. (org.quartz.core.QuartzScheduler:QuartzScheduler.java:575)
--------Current Time Is : 2018-03-06 19:08:51
--------Current Exec Time Is : 2018-03-06 19:08:51
--------Hello World!
--------Current Exec Time Is : 2018-03-06 19:08:52
--------Hello World!
--------Current Exec Time Is : 2018-03-06 19:08:54
--------Hello World!