定时器启动

上图通过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. mac上的webStorm上配置gitHub

    一,webStorm下,首先打开Preferences; 二,在Version Control目录下,选择GitHub,填写有边的内容; 注意:填写完Login和Password的以后,点击Test一 ...

  2. CodeForces 663A Rebus

    A. Rebus time limit per test 1 second memory limit per test 256 megabytes input standard input outpu ...

  3. Spoken English Practice( Believe it or not, I don't need to make believe its a big deal. (believe,deal, You don't say))

    音标复习                                                绿色:连读:红色:略读:蓝色:浊化:橙色:弱读 口语蜕变(2017/6/25) Sorry, t ...

  4. REDO 的内容:改变向量

    REDO 的内容 ---改变向量 redo的内容并不是sql语句,他是放的一些改变,叫改变向量. 数据库恢复的时候并不是执行sql语句,而是一个物理的过程,是一个数据块的覆盖.是改变数据块的大小. 可 ...

  5. Audit File Delete

    OPEN 4656 ACCESS   4663 AN OBJECT WAS DELETED 4660 CLOSE 4658 1537 = Delete 1538 = Read_CONTROL 1541 ...

  6. java获取地址全路径

      String basePath = request.getScheme()+"://"+request.getServerName()+":"+reques ...

  7. 2015-03-22——js常用的String方法

    String string.charAt(pos);  //返回字符串中pos位置处的字符.如果pos小于0或大于等于string.length返回空字符串.模拟实现:Function.prototy ...

  8. docker 构建镜像 centos7 nginx php

    #docker 构建镜像(Dockerfile) centos 7.4.1078镜像制作 nginx镜像制作(以前面centos7镜像为基础) Nginx+php镜像制作 更多操作实例,查看git里的 ...

  9. python中如何去掉unicode编码前面的u?

    1.列表类型(用join方法) myUlist = [u'AB', u'AB', u'AB', u'AB'] print myUlist print ", ".join(myUli ...

  10. What is tail-recursion

    Consider a simple function that adds the first N integers. (e.g. sum(5) = 1 + 2 + 3 + 4 + 5 = 15). H ...