Quartz实现原理

Quartz实现原理

主要组成部分:

scheduler(调度器):将job和trigger绑定在一起

job(任务)              :配置具体哪个类实现定时任务

trigger(触发器)     :配置定时器参数,如:多久执行一次,执行多上次等


        
 

Quartz工作原理

分两类线程:

  • Scheduler调度线程
  • 任务执行线程

原理

       执行常规调度的线程,常规调度线程轮询存储的所有trigger,如果有trigger到达了下一次触发的时间(用wait和notifyAll实现),则从任务执行线程池获取一个空闲线程,执行与该trigger关联的任务。


           
 

Scheduler调度线程主要有两个:

  • 执行常规调度的线程
  • 执行misfiredtrigger的线程,Misfire线程是扫描所有的trigger,查看是否有misfiredtrigger,如果有的话根据misfire的策略分别处理(fire now OR wait for the next fire)。

Quartz Job数据存储

Quartz中的trigger和job需要存储下来才能被使用。

Quartz中有两种存储方式:

  • RAMJobStore:将trigger和job存储在内存中,RAMJobStore的存取速度非常快,但是由于其在系统被停止后所有的数据都会丢失,所以在集群应用中,必须使用JobStoreSupport。
  • JobStoreSupport:是基于jdbc将trigger和job存储到数据库中。适合集群应用。

Quartz集群原理

    Quartz是在同一个数据库下,其实是使用数据库(如:MySQL)做分布式锁,当任务线程执行前加锁,执行完在finally解锁。

    Quartz中执行了如下SQL,以悲观锁的形式,对某条数据进行行锁,这样其他执行线程就必须等待

public static final String SELECT_FOR_LOCK = "SELECT * FROM "  
            + TABLE_PREFIX_SUBST + TABLE_LOCKS + " WHERE " + COL_SCHEDULER_NAME + " = " + SCHED_NAME_SUBST  
            + " AND " + COL_LOCK_NAME + " = ? FOR UPDATE"; 

具体流程如下:

0.调度器线程run()

1.获取待触发trigger

    1.1数据库LOCKS表TRIGGER_ACCESS行加锁

    1.2读取JobDetail信息

    1.3读取trigger表中触发器信息并标记为"已获取"

    1.4commit事务,释放锁

2.触发trigger

    2.1数据库LOCKS表STATE_ACCESS行加锁

    2.2确认trigger的状态(已经被获取过的trigger,就不会再执行了)

    2.3读取trigger的JobDetail信息

    2.4读取trigger的Calendar信息

    2.3更新trigger信息

    2.3commit事务,释放锁

3实例化并执行Job

    3.1从线程池获取线程执行JobRunShell的run方法


     
 

参考

http://www.jianshu.com/p/bab8e4e32952

https://www.cnblogs.com/zhenyuyaodidiao/p/4755649.html

http://blog.csdn.net/wenniuwuren/article/details/45866807

http://blog.csdn.net/tercel_opening_wing/article/details/49612497

猜你喜欢

转载自youyu4.iteye.com/blog/2404911