一、Quartz概述
Quartz是一个完全由Java编写的开源作业调度框架,为在Java应用程序中进行作业调度提供了简单却强大的机制。Quartz允许开发人员根据一定的时间间隔来调度作业。我学一样东西,从来都是从实践出发,边用边学,用起来自然就学会了。
二、使用Quartz
1、Quartz Jar
我推荐大家使用Maven来加入Jar依赖,方便而且可以对依赖有效地管理。
<dependency>
<span style="white-space:pre"> </span><groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
2、Quartz工具类,核心组件详解
我们开发不光要考虑功能的实现,还要考虑效率、耦合程度与开闭性等问题,可根据实际情况应用恰当的设计模式。回归正题:
下面这个例子很好的覆盖了Quartz最重要的4个基本要素(考验英语水平的时候到了~(>_<)~):
Scheduler:调度器,所有的作业调度都是由它控制。
Trigger: 触发器,定义触发的条件。例子中,它的类型是CronTrigger,是常见的几种触发器类型中最强大、最灵活的一类,但不要害怕,它并不是很复杂,只是多了一个Cron表达式,会在下面说到。
JobDetail: 任务细节,定义作业的标识与携带的数据。
Job:执行类,实现org.quartz.Job的接口,实现excute方法,作为作业执行体。
注意:作业真正的执行逻辑是在Job实现类中,为什么设计成JobDetail + Job结构,不直接使用Job?这是因为作业是有可能并发执行,如果Scheduler直接调度Job,就会存在对同一个Job实例并发访问的问题。而JobDetail + Job 方式,sheduler每次执行都会根据JobDetail创建一个新的Job实例,这样就可以规避并发访问的问题。
实现类代码(测试绝对可用,jar包正确导入,复制两个类,即可运行^_^):
<span style="font-size:14px;">public class JobExcuteClass implements org.quartz.Job{
//实现excute方法
@Override
public void execute(JobExecutionContext context) {
//通过context上下文对象获得map中的Job数据
JobDataMap map = context.getJobDetail().getJobDataMap();
String jobName = (String)map.get("jobName");
System.out.println(jobName + "执行");
}
}</span>
JobUtil代码:
<span style="font-size:14px;">public class JobUtil {
//声明调度器对象
private static Scheduler scheduler = null;
//Job组名
public static String GroupName = "JobsGroup";
//创建调度器对象
private static Scheduler createScheduler() throws SchedulerException {
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
return schedulerFactory.getScheduler();
}
//为调度器添加调度任务
public static void addJod(String jobName) throws SchedulerException{
//用于给Job实现类的excute方法传递数据
JobDataMap map = new JobDataMap();
map.put("jobName", jobName);
//创建JobDetail对象
//设定Job执行类,设定Job标识,设定数据map
JobDetail myJob = newJob(JobExcuteClass.class)
.withIdentity(jobName, GroupName)
.usingJobData(map)
.build();
//执行策略,Cron表达式,代表十秒执行一次
String strategy = "0/10 0/1 0/1 1/1 * ?";
//创建触发器,应用策略
CronTrigger trigger = newTrigger()
.withSchedule(cronSchedule(strategy))
.build();
//创建调度器对象
scheduler = createScheduler();
//启动调度器
scheduler.start();
//将myJob对象与trigger对象加入调度器
scheduler.scheduleJob(myJob, trigger);
}
//停止调度任务
public static void removeJob(String jobName) throws SchedulerException {
//Job标识对象
JobKey key = new JobKey(jobName, GroupName);
//注意这里一定要再次创建调度器对象,否则涉及持久化时,会抛出空指针异常
scheduler = createScheduler();
//从调度器中移除任务
scheduler.deleteJob(key);
}
//test
public static void main(String[] args) throws SchedulerException{
JobUtil.addJod("testQuartz");
}
}</span>
测试结果:每十秒打印一次数据(这里考虑到不想加过多的Quartz无关内容,没有加时间标识)
透过实例看本质,可以总结出Quartz的工作原理(转自熔岩大神的博客,说的比较好理解):
1、scheduler是一个计划调度器容器(总部),容器里面可以盛放众多的JobDetail和trigger,当容器启动后,里面的每个JobDetail都会根据trigger按部就班自动去执行。
2、JobDetail是一个可执行的工作,它本身可能是有状态的。
3、Trigger代表一个调度参数的配置,什么时候去调。
4、当JobDetail和Trigger在scheduler容器上注册后,形成了装配好的作业(JobDetail和Trigger所组成的一对儿),就可以伴随容器启动而调度执行了。
5、scheduler是个容器,容器中有一个线程池,用来并行调度执行每个作业,这样可以提高容器效率。
6、将上述的结构用一个图来表示,如下:
关于Trigger实现类(转载自:http://www.cnblogs.com/drift-ice/p/3817269.html,这篇文章里还有很多Quartz组件详解、写的很详细,就不赘述了)
Quartz有以下几种Trigger实现:
SimpleTrigger
指定从某一个时间开始,以一定的时间间隔(单位是毫秒)执行的任务。
它适合的任务类似于:9:00 开始,每隔1小时,执行一次。
它的属性有:
- repeatInterval 重复间隔
- repeatCount 重复次数。实际执行次数是 repeatCount+1。因为在startTime的时候一定会执行一次。** 下面有关repeatCount 属性的都是同理。 **
例子:
simpleSchedule()
.withIntervalInHours(