Java定时任务Quartz的配置和使用
开发微信推送的时候遇到需要定时向公众号推送满意度调查问卷,由于这些都是需要可配置的,所以我就找了找有没有可用的Java定时任务组件,Quartz这个刚好满足我的需要。现在将我使用的一些心得以及使用的工具类分享给大家!
简单介绍–Quartz
Quartz是由Java编写作业调度框架,在应用程序中进行作业调度提供了非常实用的机制。Quartz允许开发人员根据时间间隔(可以自定义时间表达式)来调度作业。它实现了任务和触发器的多对多的关系。
下面简单的介绍下我们会使用到的几个类!
org.quartz.Job
它是一个抽象接口,表示一个工作,也就是我们要执行的具体内容,重要方法:
void execute(JobExecutionContext context) ;
实现这个接口将要完成的任务业务逻辑填充在这里面。
org.quartz.JobDetail
表示具体的可执行的调度程序,Job是这个可执行程调度程序所要执行的内容,它包含了这个任务调度的方案和策略。
org.quartz.CronTrigger
表示一个调度参数的配置,通过定义和配置这个触发器,来告诉调度容器什么时候去调用JobDetail。由我们自定义的时间表达式来告诉程序我们什么时候去执行这个任务。
org.quartz.Scheduler
调度的容器,一个调度容器中可以注册多个JobDetail和Trigger。当Trigger与JobDetail组合,就可以被Scheduler容器调度了。重要方法:
void shutdown(); //停止这个任务 若传入true表示执行完这个任务再停止
void start(); //开始任务
使用–Quartz
1、动态作业的实现:由于JobDetail、CronTrigger我们是可以在运行时重新设置的,而且是在下次调用时候起作用。所以我们完全可以通过代码动态的配置我们程序的任务(当然前提是有这个需求哈!),可以将调度方案存在到配置文件(或是数据库)中,然后动态的加载这些任务。
2、JobDetail不存储具体的实例,使用时我们需要定义一个他的实例,同时它又指向JobDataMap。 JobDetail里面有Job的详细信息,如它所属的组,名称等信息。
3、JobDataMap里面存放着Job实例的对象,并保持着他们的信息,它是Map接口的实现,可以往里面添加和移除要存储的信息.
4、Scheduler调度容器包含多个JobDetail和CronTrigger。Scheduler是个调度容器,里面有一个线程池,用来并行调度执行每个作业,这样可以提高调用的效率。
5、基本使用流程
调度器线程运行run() ==> 获取待触发trigger (读取JobDetail信息,读取trigger表中触发器信息标记为”已获取”) ==> 触发trigger (确认trigger的状态,读取trigger的JobDetail信息 ,读取trigger的Calendar信息 ,更新trigger信息) ==> 实例化并执行Job (从线程池获取线程执行JobRunShell的run方法)
初始化一个调度容器,从工厂类获取实例
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sch = sf.getScheduler();
定义我们自己的任务
JobDetail jobDetail = new JobDetail(jobName, DEFAULT_JOB_GROUP_NAME, doClass);//具体任务,参数: 任务名,任务分组,任务执行类
定义触发器
CronTrigger trigger = new CronTrigger(jobName, DEFAULT_TRIGGER_GROUP_NAME); //时间触发器,参数: 触发器名,触发器组
trigger.setCronExpression(time);
将任务和触发器添加到调度容器
sched.scheduleJob(jobDetail, trigger);
启动任务
if (!sched.isShutdown()) {
sched.start();
}
工具分享–Quartz
工具类对于开发来讲是必不可少的,我相信有的人可能就直接跳过上面的内容直接来这边复制工具类了,不过我还是建议大家看下上面的内容,加深下对于Quartz整体的一个了解!话不多说,下面就是我所使用的工具类
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;
/**
* @Description: 定时任务管理类
* @ClassName: QuartzJobManager
* @author hjf
* @date 2017-06-30
*/
public class QuartzJobManager {
private static SchedulerFactory mySchedulerFactory = new StdSchedulerFactory();
//统一任务分组名
private static String DEFAULT_JOB_GROUP_NAME = "DEFAULT";
//统一触发器分组名
private static String DEFAULT_TRIGGER_GROUP_NAME = Scheduler.DEFAULT_GROUP;
/**
* @Description: 默认添加一个定时任务
* @param jobName 任务名
* @param doClass 任务
* @param time 时间设置,参考quartz说明文档
* @author hjf
* @date 2017-06-30
*/
@SuppressWarnings({ "rawtypes" })
public static void addJob(String jobName, Class doClass, String time) {
try {
//从工厂获取一个调度
Scheduler sched = mySchedulerFactory.getScheduler();
JobDetail jobDetail = new JobDetail(jobName, DEFAULT_JOB_GROUP_NAME, doClass);//具体任务,参数: 任务名,任务分组,任务执行类
CronTrigger trigger = new CronTrigger(jobName, DEFAULT_TRIGGER_GROUP_NAME); //时间触发器,参数: 触发器名,触发器组
trigger.setCronExpression(time); //触发器时间设定(时间表达式)
sched.scheduleJob(jobDetail, trigger); //将任务详情和时间情况添加到调度
//启动
if (!sched.isShutdown()) {
sched.start();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description: 自定义添加一个定时任务
* @param jobName 任务名
* @param jobGroupName 任务组名
* @param triggerName 触发器名
* @param triggerGroupName 触发器组名
* @param doClass 任务
* @param time 时间设置,参考quartz说明文档
* @author hjf
* @date 2017-06-30
*/
@SuppressWarnings("rawtypes")
public static void addJob(String jobName, String jobGroupName,
String triggerName, String triggerGroupName, Class doClass,
String time) {
try {
//从工厂获取一个调度
Scheduler sched = mySchedulerFactory.getScheduler();
JobDetail jobDetail = new JobDetail(jobName, jobGroupName, doClass);//具体任务,参数: 任务名,任务分组,任务执行类
CronTrigger trigger = new CronTrigger(triggerName, triggerGroupName);//时间触发器,参数: 触发器名,触发器组
trigger.setCronExpression(time);//触发器时间设定(时间表达式)
sched.scheduleJob(jobDetail, trigger);//将任务详情和时间情况添加到调度
//启动
if (!sched.isShutdown()) {
sched.start();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description: 修改一个任务的触发时间
* 先移除原来旧的job再添加新的job
* @param jobName 任务名
* @param time 时间表达式
* @author hjf
* @date 2017-06-30
*/
@SuppressWarnings("rawtypes")
public static void modifyJobTime(String jobName, String time) {
try {
Scheduler sched = mySchedulerFactory.getScheduler();
CronTrigger trigger = (CronTrigger) sched.getTrigger(jobName,DEFAULT_TRIGGER_GROUP_NAME);
if (trigger == null) {
return;
}
String oldTime = trigger.getCronExpression(); //获取旧的时间表达式
if (!oldTime.equalsIgnoreCase(time)) {
JobDetail jobDetail = sched.getJobDetail(jobName,DEFAULT_JOB_GROUP_NAME); //获取任务详情
Class objJobClass = jobDetail.getJobClass();
removeJob(jobName); //移除旧任务
addJob(jobName, objJobClass, time); //添加新的任务
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description: 修改一个任务的触发时间
* @param triggerName 触发器名称
* @param triggerGroupName 触发器组名
* @param time 时间表达式
* @author hjf
* @date 2017-06-30
*/
public static void modifyJobTime(String triggerName,String triggerGroupName, String time) {
try {
Scheduler sched = mySchedulerFactory.getScheduler();
CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerName,triggerGroupName);
if (trigger == null) {
return;
}
//获取旧的时间表达式
String oldTime = trigger.getCronExpression();
if (!oldTime.equalsIgnoreCase(time)) {
CronTrigger ct = (CronTrigger) trigger;
// 修改时间
ct.setCronExpression(time);
// 重启触发器
sched.resumeTrigger(triggerName, triggerGroupName);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description: 移除一个任务 使用默认配置
* @param jobName 任务名
* @author hjf
* @date 2017-06-30
*/
public static void removeJob(String jobName) {
try {
Scheduler sched = mySchedulerFactory.getScheduler();
sched.pauseTrigger(jobName, DEFAULT_TRIGGER_GROUP_NAME); // 停止触发器
sched.unscheduleJob(jobName, DEFAULT_TRIGGER_GROUP_NAME); // 移除触发器
sched.deleteJob(jobName, DEFAULT_JOB_GROUP_NAME); // 删除任务
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description: 移除一个任务 自定义配置
* @param jobName 任务名
* @param jobGroupName 任务组名
* @param triggerName 触发器名
* @param triggerGroupName 触发器组名
* @author hjf
* @date 2017-06-30
*/
public static void removeJob(String jobName, String jobGroupName,String triggerName, String triggerGroupName) {
try {
Scheduler sched = mySchedulerFactory.getScheduler();
sched.pauseTrigger(triggerName, triggerGroupName); // 停止触发器
sched.unscheduleJob(triggerName, triggerGroupName); // 移除触发器
sched.deleteJob(jobName, jobGroupName); // 删除任务
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description:启动定时的任务
* @author hjf
* @date 2017-06-30
*/
public static void startJobs() {
try {
Scheduler sched = mySchedulerFactory.getScheduler();
sched.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description:关闭定时任务
* @author hjf
* @date 2017-06-30
*/
public static void shutdownJobs() {
try {
Scheduler sched = mySchedulerFactory.getScheduler();
if (!sched.isShutdown()) {
sched.shutdown();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
小结–Quartz
对于Quartz的基本使用就是这些内容了,关于时间表达示以及Quartz运行机制的分析可能会在后面的博文中给出(不过这个博主有点懒啊,希望大家多多支持,您的支持就是对我最大的鼓励)。
谢谢大家的支持,转载请注明出处!