Quartz与Spring集成——创建调度器

Posted 泰山不老生

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Quartz与Spring集成——创建调度器相关的知识,希望对你有一定的参考价值。

前言

在《Quartz与Spring集成—— SchedulerFactoryBean的初始化分析》一文中介绍过Spring集成Quartz时的初始化过程,其中简单的提到了创建调度器的方法createScheduler。本文将着重介绍Quartz初始化时是如何创建调度器的。

创建调度器

这里从createScheduler的实现(见代码清单1)来分析,其处理步骤如下:

  1. 设置线程上下文的类加载器;
  2. 通过单例方法获取SchedulerRepository的实例(见代码清单2);
  3. 从调度仓库实例SchedulerRepository中查找已经存在的调度器,这里想说的是虽然此实现考虑到了多线程安全问题,不过这种方式效率较低。不如提前初始化,由final修饰,不使用同步语句,避免线程间的阻塞和等待;
  4. 获取调取器(见代码清单3),其实际上首先从调度器缓存中查找调度器,否则调用instantiate方法创建调度器;
  5. 检查重新获取的调度器和已经存在的调度器是否相同,如果相同则说明此调度器已经被激活了,将会报出异常。如果调度器是首次被激活,那么将返回此调度器。这里的实现稍微有些拖沓,其实只有当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;
    }