quartz2.2源码分析
前言
Quartz是一款由java写成的作业调度框架,在大量javase/javaee应用中被用来做定时任务,它功能强大而又不失使用简单性。
使用例子
maven引入:
org.quartz-scheduler
quartz
2.2.2
加入配置文件org/quartz/quartz.properties,使用源码包里面默认配置即可:
org.quartz.scheduler.instanceName: DefaultQuartzScheduler
org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 20
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
org.quartz.jobStore.misfireThreshold: 60000
org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
例子代码:
调度管理类:
import java.util.HashMap;
import java.util.Map;
import org.quartz.DateBuilder;
import org.quartz.DateBuilder.IntervalUnit;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
public class QuartzManager {
private static SchedulerFactory gSchedulerFactory = new StdSchedulerFactory();
private static String HM_JOB = "HM_JOB";
private static String HM_TRIGGER = "HM_TRIGGER";
/**
* 增加任务
* @param jobClass 任务实现类
* @param jobName 任务名称
* @param interval 间隔时间
* @param data 数据
*/
public static void addJob(Class extends Job> jobClass, String jobName, int interval, Map data) {
try {
Scheduler sched = gSchedulerFactory.getScheduler();
JobDetail jobDetail = JobBuilder.newJob(jobClass)
.withIdentity(jobName, HM_JOB)//任务名称和组构成任务key
.build();
jobDetail.getJobDataMap().putAll(data);
// 触发器
SimpleTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity(jobName, HM_TRIGGER)//触发器key
.startAt(DateBuilder.futureDate(1, IntervalUnit.SECOND))
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(interval)
.repeatForever())
.build();
sched.scheduleJob(jobDetail, trigger);
// 启动
if (!sched.isShutdown()) {
sched.start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 删除任务
*
* @param jobName 任务名称
*/
public static void removeJob(String jobName) {
try {
Scheduler sched = gSchedulerFactory.getScheduler();
sched.deleteJob(new JobKey(jobName, HM_JOB));
} catch (Exception e) {
e.printStackTrace();
}
}
}
实现Job自定义任务类:
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class TestJob implements Job {
public void execute(JobExecutionContext jobexecutioncontext) throws JobExecutionException {
String id = jobexecutioncontext.getJobDetail().getJobDataMap().getString("id");
System.out.println("threadId: " + Thread.currentThread().getId() + ", id: " + id);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
main:
public static void main(String[] args) throws InterruptedException {
Map map = new HashMap();
map.put("id", "1");
addJob(TestJob.class, "aaa", 1, map);
map.clear();
map.put("id", "2");
addJob(TestJob.class, "bbb", 1, map);
Thread.sleep(3000);
removeJob("aaa");
System.out.println("main end----------");
Thread.sleep(3000);
System.exit(1);
}
结果:
threadId: 12, id: 2
threadId: 11, id: 1
threadId: 13, id: 1
threadId: 14, id: 2
threadId: 15, id: 1
threadId: 16, id: 2
main end----------
threadId: 17, id: 2
threadId: 18, id: 2
threadId: 19, id: 2
工作原理
Quartz是通过对用户暴露出Scheduler来进行任务的操作,它可以把任务JobDetail和触发器Trigger加入任务池中,可以把任务删除,也可以把任务停止,scheduler把这些任务和触发器放到一个JobStore中,这里jobStore有内存形式的也有持久化形式的,当然也可以自定义扩展成独立的服务。
它内部会通过一个调度线程QuartzSchedulerThread不断到JobStore中找出下次需要执行的任务,并把这些任务封装放到一个线程池ThreadPool中运行,它的组件结构如下图:
1.Job就是自定义业务的接口,里面就一个execute方法,线程运行Job时会把JobDataMap封装到JobExecutionContext里作为execute方法的参数,jobdetail是对job的封装,里面有Job的class,对应的数据, 名称,分组等
2.Trigger是触发器,job下次什么时候执行存放在trigger中
3.QuartzSchedulerResources相当于调度的资源存放器,包含了JobStore, ThreadPool等资源,调度都是通过 QuartzSchedulerResources获取相关属性的。
4.jobStore是任务和触发器存储地方,它里面提供大量类似于增删改的操作任务方法。
5.QuartzSchedulerThread是一个调度线程,ThreadPool是一个执行线程池,下图是运行后的线程栈:
1-使用和原理