Quartz与Spring集成——创建调度器
Posted 泰山不老生
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Quartz与Spring集成——创建调度器相关的知识,希望对你有一定的参考价值。
前言
在《Quartz与Spring集成—— SchedulerFactoryBean的初始化分析》一文中介绍过Spring集成Quartz时的初始化过程,其中简单的提到了创建调度器的方法createScheduler。本文将着重介绍Quartz初始化时是如何创建调度器的。
创建调度器
这里从createScheduler的实现(见代码清单1)来分析,其处理步骤如下:
- 设置线程上下文的类加载器;
- 通过单例方法获取SchedulerRepository的实例(见代码清单2);
- 从调度仓库实例SchedulerRepository中查找已经存在的调度器,这里想说的是虽然此实现考虑到了多线程安全问题,不过这种方式效率较低。不如提前初始化,由final修饰,不使用同步语句,避免线程间的阻塞和等待;
- 获取调取器(见代码清单3),其实际上首先从调度器缓存中查找调度器,否则调用instantiate方法创建调度器;
- 检查重新获取的调度器和已经存在的调度器是否相同,如果相同则说明此调度器已经被激活了,将会报出异常。如果调度器是首次被激活,那么将返回此调度器。这里的实现稍微有些拖沓,其实只有当existingScheduler为null时,才会调用instantiate方法创建newScheduler,也只有在这个时候newScheduler才不等于existingScheduler,并且不会抛出异常。因此我们甚至可以省去Scheduler existingScheduler = (schedulerName != null ? repository.lookup(schedulerName) : null);这行代码,而直接将代码清单3中的实现进行修改——当sched为null时才调用instantiate方法创建调度器。
代码清单1
protected Scheduler createScheduler(SchedulerFactory schedulerFactory, String schedulerName)
throws SchedulerException {
// Override thread context ClassLoader to work around naive Quartz ClassLoadHelper loading.
Thread currentThread = Thread.currentThread();
ClassLoader threadContextClassLoader = currentThread.getContextClassLoader();
boolean overrideClassLoader = (this.resourceLoader != null &&
!this.resourceLoader.getClassLoader().equals(threadContextClassLoader));
if (overrideClassLoader) {
currentThread.setContextClassLoader(this.resourceLoader.getClassLoader());
}
try {
SchedulerRepository repository = SchedulerRepository.getInstance();
synchronized (repository) {
Scheduler existingScheduler = (schedulerName != null ? repository.lookup(schedulerName) : null);
Scheduler newScheduler = schedulerFactory.getScheduler();
if (newScheduler == existingScheduler) {
throw new IllegalStateException("Active Scheduler of name '" + schedulerName + "' already registered " +
"in Quartz SchedulerRepository. Cannot create a new Spring-managed Scheduler of the same name!");
}
if (!this.exposeSchedulerInRepository) {
// Need to remove it in this case, since Quartz shares the Scheduler instance by default!
SchedulerRepository.getInstance().remove(newScheduler.getSchedulerName());
}
return newScheduler;
}
}
finally {
if (overrideClassLoader) {
// Reset original thread context ClassLoader.
currentThread.setContextClassLoader(threadContextClassLoader);
}
}
}
代码清单2
public static synchronized SchedulerRepository getInstance() {
if (inst == null) {
inst = new SchedulerRepository();
}
return inst;
}
代码清单3
以上是关于Quartz与Spring集成——创建调度器的主要内容,如果未能解决你的问题,请参考以下文章
Quartz与Spring集成——QuartzSchedulerThread的执行分析