一、简介
我这里的分析采用的是quartz-2.2.1的简单配置。
1. 用的线程池是quartz自带的org.quartz.simpl.SimpleThreadPool;
2. 采用org.quartz.impl.StdSchedulerFactory.getScheduler()来获取Scheduler;
3. Job的存储方案采用org.quartz.simpl.RAMJobStore;
4. 采用org.quartz.impl.StdJobRunShellFactory. createJobRunShell()来得到JobRunShell;
5. 主线程org.quartz.core.QuartzSchedulerThread在初始化时被创建出来,一直等到关闭应用时才会停止;
6. 采用org.quartz.core.JobRunShell运行Job;
7. 采用工具类org.quartz.core.QuartzSchedulerResources来存储执行过程中需要的对象,包括线程池(threadPool)、Job的存储对象(jobStore)、获取Job运行的工厂(jobRunShellFactory)等;
二、Job具体运行流程分析
1. org.quartz.core.QuartzScheduler.QuartzScheduler(QuartzSchedulerResources, long, long)在初始化时会生成主线程QuartzSchedulerThread并运行,代码如下:
2. org.quartz.core.QuartzSchedulerThread.run():主线程(Job的启动者)中是一个相当于是一个死循环,代码如下:
只有当定时任务应用关闭时调用org.quartz.core.QuartzScheduler.shutdown(boolean)才会停止,
org.quartz.core.QuartzSchedulerThread.halt(boolean);代码如下:
(上述代码中join()方法的调用时让子线程执行完毕之后再往下执行,该句代码的意义是等待所有的定时任务结束在停止应用程序)。
3.经过上面的分析我们知道了,Job的启动的由来,下面我们具体分析一个job的运行过程。org.quartz.core.QuartzSchedulerThread.run()中,
该代码片段表示只有当paused=false时才会往下执行,而要让paused=false只有等到togglePause(false)被调用唤起,而Scheduler.start()会调用togglePause()调用。
org.quartz.core.QuartzSchedulerThread.run():
初始化JobRunShell,然后采用线程池运行JobRunShell。多线程部分的控制代码如下:
org.quartz.simpl.SimpleThreadPool.runInThread(Runnable):
(1) 等待可用线程不为空再往下执行;
(2) 从可用线程集合中取出一个线程并从中移除,并将该线程加入到忙碌线程集合中
(3) 调用org.quartz.simpl.SimpleThreadPool.WorkerThread.run(Runnable)方法:
这里开启一个JobRunShell,用runnabel这个变量进行控制。如果runnable不为空,说明该线程正在运行。如果为空往下执行将runnable赋值。赋值完之后,org.quartz.simpl.SimpleThreadPool.WorkerThread.run()监听到,程序往下执行,代码如下:
如果runnable为空,则一直轮询,等到runnbale不为空,程序往下执行调用org.quartz.core.JobRunShell.run()。
job启动。