定时器启动

上图通过spring加载quartz

<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
...
</bean>

SpringContext在加载SchedulerFactoryBean时会去加载他的afterPropertiesSet方法,而SchedulerFactoryBean会去与quartz的StdSchedulerFactory交互初使化配置,StdSchedulerFactory会create类QuartzScheduler,
QuartzScheduler会启动总控制线程QuartzSchedulerThread不停的轮循。

类目结构如下

1、StdSchedulerFactory是工厂类,还有一个工厂类DirectSchedulerFactory比较简单,而StdSchedulerFactory是可以加载各种属性的。属性的加载initialize方法,Contants里面都是参数,可以按说明在quartz.properties上加。

2、StdSchedule只是QuartzSchedule的一个包装类,方法更清晰。

3、QuartzScheduler是整个定时任务框架工作的核心类,上面的类图仅仅展现了QuartzScheduler中几个核心成员。

4、QuartzSchedulerResources可以认为是存放一切配置以及通过配置初始化出来的一些资源的容器,其中包括了存储job定义的jobStore

5、JobStore可以有多种实现,我们使用的是默认的RAMJobStore;

6、ThreadPool,还有一个非常重要的对象就是ThreadPool,这个线程池管理着执行我们定义的Job所需的所有线程。这个线程池的大小配置就是通过我上面提到过的“org.quartz.threadPool.threadCount”进行配置的。

QuartzScheduler另一个重要成员就是QuartzSchedulerThread,没有这个线程的话我们所有定义的任务都不会被触发执行,也就是说它是Quartz后台的“守护线程”,它不断的去查找合适的job并触发这些Job执行。

StdSchedulerFactory.getSchedule只是启动了QuartzSchedulerThread线程,开关未打开。
Scheduler.start()才是打开QuartzSchedulerThread的开关,真正开始线程轮循。
当总线程QuartzSchedulerThread处理完了数据库对TRIGGER操作后,就开始把任务放到线程中执行了。

QuartzSchedulerThread轮询流程

quartz运行时由QuartzSchedulerThread类作为主体,循环执行调度流程。JobStore作为中间层,按照quartz的并发策略执行数据库操作,完成主要的调度逻辑。JobRunShellFactory负责实例化JobDetail对象,将其放入线程池运行。LockHandler负责获取LOCKS表中的数据库锁。

处理流程

第一部分:获取trigger

1、通知JobStore获取待触发的TRIGGER
2、JobStore获取数据库锁(获取TRIGGER),获取trigger_access的行级锁
3、JobStore获取30s内触发且状态为waiting的TRIGGER
4、获取这些TRIGGER关联的job信息
5、将这些TRIGGER的状态置为acquired
6、将待触发的TRIGGER插入表中QRTZ_FIRED_TRIGGERS
7、提交获取TRIGGER的事务,行级锁被释放
8、返回待触发的TRIGGER列表

第二部分:触发trigger

10、通知JobStore触发TRIGGER
11、JobStore获取数据库锁(触发)TRIGGER,获取stat_access行级锁
12、JobStore确认TRIGGER状态
13、读取job信息
14、读取TRIGGER的calendar信息
15、更新TRIGGER的信息至executing
16、根据信息,更新TRIGGER状态至阻塞、终结、等待等状态
17、持久化TRIGGER,更新下次触发时间等
18、提交触发TRIGGER的事务,行级锁被释放
19、返回待执行的jobDetail对象

第三部分:实例化并执行Job

根据待执行的jobDetail列表,实例化job,并将其放入线程池中运行

可以看到,这个过程中有两个相似的过程:同样是对数据表的更新操作,同样是在执行操作前获取锁 操作完成后释放锁.这一规则可以看做是quartz解决集群问题的核心思想。
一个调度器实例在执行涉及到分布式问题的数据库操作前,首先要获取QUARTZ2_LOCKS表中对应当前调度器的行级锁,获取锁后即可执行其他表中的数据库操作,随着操作事务的提交,行级锁被释放,供其他调度器实例获取。
集群中的每一个调度器实例都遵循这样一种严格的操作规程,那么对于同一类调度器来说,每个实例对数据库的操作只能是串行的.而不同名的调度器之间却可以并行执行。

参考链接:http://www.cnblogs.com/davidwang456/p/4205237.html

其他参考:http://www.cnblogs.com/surprizeFuture/articles/4564293.html

quartz(7)-源码分析的更多相关文章

  1. quartz集群调度机制调研及源码分析---转载

    quartz2.2.1集群调度机制调研及源码分析引言quartz集群架构调度器实例化调度过程触发器的获取触发trigger:Job执行过程:总结:附: 引言 quratz是目前最为成熟,使用最广泛的j ...

  2. 定时组件quartz系列<三>quartz调度机制调研及源码分析

    quartz2.2.1集群调度机制调研及源码分析引言quartz集群架构调度器实例化调度过程触发器的获取触发trigger:Job执行过程:总结:附: 引言 quratz是目前最为成熟,使用最广泛的j ...

  3. (1)quartz集群调度机制调研及源码分析---转载

    quartz2.2.1集群调度机制调研及源码分析 原文地址:http://demo.netfoucs.com/gklifg/article/details/27090179 引言quartz集群架构调 ...

  4. Quartz源码分析

    先简单介绍一下quartz,Quartz是一个功能丰富的开源作业调度库,可以集成到几乎任何Java应用程序中 - 从最小的独立应用程序到最大的电子商务系统.quartz可用于创建执行数十,数百甚至数十 ...

  5. quartz源码分析——执行引擎和线程模型

    title: quartz源码分析--执行引擎和线程模型 date: 2017-09-09 23:14:48 categories: quartz tags: [quartz, 源码分析] --- - ...

  6. Quartz源码——QuartzSchedulerThread.run() 源码分析(三)

    QuartzSchedulerThread.run()是主要处理任务的方法!下面进行分析,方便自己查看! 我都是分析的jobStore 方式为jdbc的SimpleTrigger!RAM的方式类似分析 ...

  7. Quartz源码——scheduler.start()启动源码分析(二)

    scheduler.start()是Quartz的启动方式!下面进行分析,方便自己查看! 我都是分析的jobStore 方式为jdbc的SimpleTrigger!RAM的方式类似分析方式! Quar ...

  8. Quartz源码——JobStore保存JonDetail和Trigger源码分析(一)

    我都是分析的jobStore 方式为jdbc的SimpleTrigger!RAM的方式类似分析方式! {0} :表的前缀 ,如表qrtz_trigger ,{0}== qrtz_ {1}:quartz ...

  9. [源码分析] 定时任务调度框架 Quartz 之 故障切换

    [源码分析] 定时任务调度框架 Quartz 之 故障切换 目录 [源码分析] 定时任务调度框架 Quartz 之 故障切换 0x00 摘要 0x01 基础概念 1.1 分布式 1.1.1 功能方面 ...

随机推荐

  1. python 保存csv文件

    利用pandas库, 将numpy的array数据保存成csv格式的文件: import pandas as pd import numpy as np data = pd.read_csv('C:\ ...

  2. ryu启动问题总结

    在Mininet中启动ryu控制器,首先切换到ryu中的app目录下: cd ryu/ryu/app 启动ryu: ryu-manager simple_switch.py 遇到了如下的错误提示: 这 ...

  3. poj3414

    Pots Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13545   Accepted: 5717   Special J ...

  4. Caused by: java.lang.IllegalArgumentException: @EnableAsync annotation metadata was not injected

    需要注意的是ComponentScan 不能扫描 org.springframework 否则会报错,要扫描指定的package才行

  5. 巨蟒python全栈开发flask4

    1.偏函数 2.ThreadingLocal线程安全 空间换取时间 3.LocalStack 4.RunFlask+request 5.请求上文 6.请求下文

  6. mysql_注入语句

    查看mysql中所有的用户及权限(只有root权限才能看). mysql> select distinct concat(user,host) from mysql.user; ======== ...

  7. sqlalchemy(二)高级用法 2

    转自:https://www.cnblogs.com/coder2012/p/4746941.html 外键以及relationship 首先创建数据库,在这里一个user对应多个address,因此 ...

  8. TI C66x DSP 系统events及其应用 - 5.7(IST)

    当CPU開始处理一个中断(INT4~15)时,它将引用中断服务表(IST).IST是一个获取包括中断服务代码的包的表. IST包括16个连续的获取包.每个中断服务获取包(ISFP)包括最多14条指令( ...

  9. Activity # runOnUiThread 与 View # post

    There is no real difference, except that the View.post is helpful when you don't have a direct acces ...

  10. pandas(四)唯一值、值计数以及成员资格

    针对Series对象,从中抽取信息 unique可以得到Series对象的唯一值数组 >>> obj = Series(['c','a','d','a','a','b','b','c ...