quartz2.2源码分析2-scheduler初始化及使用

原创
2016/05/12 16:48
阅读数 5.7K

scheduler初始化

先看个图:

  • 1. SchedulerFacotory是一个接口,它有两个实现,StdSchedulerFacotory根据配置文件来创建Scheduler,DirectSchedulerFactory 主要通过编码对Scheduler控制,通常为了侵入性更小、实现更方便我们用StdSchedulerFacotory类型来创建StdScheduler,quartz.properties里面的配置都对应到这个StdSchedulerFactory中,所以对某个配置不明白已经该配置的默认值可以看StdSchedulerFactory中获取配置的代码。
  • 2. 初始化流程第一步就是加载配置文件,第二步就是根据配置项创建各种对象。
public Scheduler getScheduler() throws SchedulerException {
        // 第一步:加载配置文件,System的properties覆盖前面的配置
        if (cfg == null) {
            initialize();
        }
        SchedulerRepository schedRep = SchedulerRepository.getInstance();
        Scheduler sched = schedRep.lookup(getSchedulerName());
        if (sched != null) {
            if (sched.isShutdown()) {
                schedRep.remove(getSchedulerName());
            } else {
                return sched;
            }
        }
        // 第二步:初始化,生成scheduler
        sched = instantiate();
        return sched;
    }
  • 3. 从第二步开始开代码,工厂调用getScheduler()方法后进入instantiate()方法,开始就会看到很多需要初始化的对象,下面代码都是在 instantiate()方法 中:

        //需要创建获取的属性在这边
        JobStore js = null;
        ThreadPool tp = null;
        QuartzScheduler qs = null;
        DBConnectionManager dbMgr = null;
        String instanceIdGeneratorClass = null;
        Properties tProps = null;
        String userTXLocation = null;
        boolean wrapJobInTx = false;
        boolean autoId = false;
        long idleWaitTime = -1;
        long dbFailureRetry = 15000L; // 15 secs
        String classLoadHelperClass;
        String jobFactoryClass;
        ThreadExecutor threadExecutor;

  • 4.上图中第5步是个重头戏,看代码,里面初始化了很多东西,线程也是在这里面起的,选几个核心的代码看看:

创建线程池:

// 创建线程池,这个在配置文件里面配线程池类名
String tpClass = cfg.getStringProperty(PROP_THREAD_POOL_CLASS, SimpleThreadPool.class.getName());
if (tpClass == null) {
	initException = new SchedulerException("ThreadPool class not specified. ");
	throw initException;
}
try {
	tp = (ThreadPool) loadHelper.loadClass(tpClass).newInstance();
} catch (Exception e) {
	initException = new SchedulerException("ThreadPool class '" + tpClass + "' could not be instantiated.", e);
	throw initException;
}
tProps = cfg.getPropertyGroup(PROP_THREAD_POOL_PREFIX, true);
try {
	setBeanProps(tp, tProps);// ?
} catch (Exception e) {
	initException = new SchedulerException("ThreadPool class '" + tpClass + "' props could not be configured.",
			e);
	throw initException;
}

创建jobStore:

// 创建jobStore, jobstore也是在配置文件配的
String jsClass = cfg.getStringProperty(PROP_JOB_STORE_CLASS, RAMJobStore.class.getName());
if (jsClass == null) {
	initException = new SchedulerException("JobStore class not specified. ");
	throw initException;
}
try {
	js = (JobStore) loadHelper.loadClass(jsClass).newInstance();
} catch (Exception e) {
	initException = new SchedulerException("JobStore class '" + jsClass + "' could not be instantiated.", e);
	throw initException;
}
SchedulerDetailsSetter.setDetails(js, schedName, schedInstId);
tProps = cfg.getPropertyGroup(PROP_JOB_STORE_PREFIX, true, new String[] { PROP_JOB_STORE_LOCK_HANDLER_PREFIX });
try {
	setBeanProps(js, tProps);
} catch (Exception e) {
	initException = new SchedulerException("JobStore class '" + jsClass + "' props could not be configured.",
			e);
	throw initException;
}

创建其他对象都一样,根据配置文件配的类名称用反射创建对象。

最后把上面创建的对方放到QuartzSchedulerResources中并把线程池起来,这个相当于 QuartzScheduler 的资源存放处,如下:

QuartzSchedulerResources rsrcs = new QuartzSchedulerResources();
rsrcs.setName(schedName);
rsrcs.setThreadName(threadName);
rsrcs.setInstanceId(schedInstId);
rsrcs.setJobRunShellFactory(jrsf);
rsrcs.setMakeSchedulerThreadDaemon(makeSchedulerThreadDaemon);
rsrcs.setThreadsInheritInitializersClassLoadContext(threadsInheritInitalizersClassLoader);
rsrcs.setRunUpdateCheck(!skipUpdateCheck);
rsrcs.setBatchTimeWindow(batchTimeWindow);
rsrcs.setMaxBatchSize(maxBatchSize);
rsrcs.setInterruptJobsOnShutdown(interruptJobsOnShutdown);
rsrcs.setInterruptJobsOnShutdownWithWait(interruptJobsOnShutdownWithWait);
rsrcs.setJMXExport(jmxExport);
rsrcs.setJMXObjectName(jmxObjectName);

//这个线程执行者用于后面启动调度线程
rsrcs.setThreadExecutor(threadExecutor);
threadExecutor.initialize();

rsrcs.setThreadPool(tp);
if (tp instanceof SimpleThreadPool) {
	if (threadsInheritInitalizersClassLoader)
		((SimpleThreadPool) tp).setThreadsInheritContextClassLoaderOfInitializingThread(
				threadsInheritInitalizersClassLoader);
}
//执行线程池启动
tp.initialize();
tpInited = true;

rsrcs.setJobStore(js);

// add plugins
for (int i = 0; i < plugins.length; i++) {
	rsrcs.addSchedulerPlugin(plugins[i]);
}

//调度线程在构造方法里面启动的
qs = new QuartzScheduler(rsrcs, idleWaitTime, dbFailureRetry);

总体的逻辑是根据配置文件相关设置创建线程池,调度,jobstore等对象,然后都存放到quartzSchedulerResources,后续quartzScheduler需要用到上面对象都是通过quartzSchedulerResources操作。

scheduler 使用

以我们常用的scheduleJob(JobDetail jobDetail, Trigger trigger)方法来说明 scheduler 内部调用流程,如下图:

quartzScheduler都是通过quartzSchedulerResources获取jobStore,然后把任务和触发器放到jobStore中,后面调度线程会对JobStore中任务进行调度。

展开阅读全文
加载中

作者的其它热门文章

打赏
4
4 收藏
分享
打赏
0 评论
4 收藏
4
分享
返回顶部
顶部