Quartz源码解析 ---- 触发器按时启动原理
来源:互联网 发布:深圳悍马军品淘宝店 编辑:程序博客网 时间:2024/06/05 14:34
从线程开始, 我们来看下QuartzSchedulerThread类(负责执行触发的Trigger的工作) :
@Override public void run() { boolean lastAcquireFailed = false; while (!halted.get()) { try { // check if we're supposed to pause... synchronized (sigLock) { while (paused && !halted.get()) { try { // wait until togglePause(false) is called... sigLock.wait(1000L); } catch (InterruptedException ignore) { } } if (halted.get()) { break; } } int availThreadCount = qsRsrcs.getThreadPool().blockForAvailableThreads();
使用了AtomicBoolean类halted.get()检查触发器是否是暂停状态, 早期版本的Quartz用的还是Boolean, AtomicBoolean类只有在值稳定后才会更新, 保持操作原子性。 从上面代码可以看出, 只要是触发器停止状态或者等待状态, Thread就会一直wait。sigLock同步对象用来随时唤醒将被触发的Trigger(使用notifyAll来进行对wait中线程的唤醒, 如下源码)
synchronized(sigLock) { signaled = true; signaledNextFireTime = candidateNewNextFireTime; sigLock.notifyAll(); }
qsRsrcs.getThreadPool().blockForAvailableThreads() // 获取线程池现在可以用线程数
跟Spring集成的配置(建议一般使用10~50个线程): 下面一行代码配置了最大线程数
<prop key="org.quartz.threadPool.threadCount">40</prop>
接上面run方法代码:
if(availThreadCount > 0) { // will always be true, due to semantics of blockForAvailableThreads... List<OperableTrigger> triggers = null; long now = System.currentTimeMillis(); clearSignaledSchedulingChange(); try { // 查找30秒内一定数量的Trigger triggers = qsRsrcs.getJobStore().acquireNextTriggers( now + idleWaitTime, Math.min(availThreadCount, qsRsrcs.getMaxBatchSize()), qsRsrcs.getBatchTimeWindow()); lastAcquireFailed = false; ... } ... if (triggers != null && !triggers.isEmpty()) { now = System.currentTimeMillis(); long triggerTime = triggers.get(0).getNextFireTime().getTime(); long timeUntilTrigger = triggerTime - now; while(timeUntilTrigger > 2) { synchronized (sigLock) { if (halted.get()) { break; } if (!isCandidateNewTimeEarlierWithinReason(triggerTime, false)) { try { // we could have blocked a long while // on 'synchronize', so we must recompute now = System.currentTimeMillis(); timeUntilTrigger = triggerTime - now; if(timeUntilTrigger >= 1) sigLock.wait(timeUntilTrigger); } catch (InterruptedException ignore) { } } ... } ... boolean goAhead = true; synchronized(sigLock) { goAhead = !halted.get(); } if(goAhead) { try { List<TriggerFiredResult> res = qsRsrcs.getJobStore().triggersFired(triggers); if(res != null) bndles = res; } ... } for (int i = 0; i < bndles.size(); i++) { ... if (bndle == null) { qsRsrcs.getJobStore().releaseAcquiredTrigger(triggers.get(i)); continue; }
availThreadCount必然大于0, 因为肯定至少得有一个线程来处理Trigger。
以上代码基本上做的就是以下轮询(服务器启动后不断地执行run方法):
qsRsrcs.getJobStore().acquireNextTriggers【查找即将触发的Trigger】 ---->
sigLock.wait(timeUntilTrigger)【等待执行】 ---->
qsRsrcs.getJobStore().triggersFired(triggers)【执行】---->
qsRsrcs.getJobStore().releaseAcquiredTrigger(triggers.get(i)) 【释放Trigger】
- Quartz源码解析 ---- 触发器按时启动原理
- Quartz源码解析 ---- 触发器按时启动原理
- Quartz原理解析
- quartz源码解析(一)
- quartz 相关源码解析
- 关于Spirng Quartz定时触发器+源码示例!
- spring Quartz 源码分析--触发器类CronTriggerBean源码剖析
- spring Quartz 源码分析--触发器类SimpleTriggerBean源码剖析
- Quartz源码分析(一)------ 以线程等待的方式实现按时间调度
- Quartz源码分析(一)------ 以线程等待的方式实现按时间调度
- Quartz源码分析(一)------ 以线程等待的方式实现按时间调度
- Quartz源码分析(一)------ 以线程等待的方式实现按时间调度
- java quartz 中的时间格式 及启动定时器 触发器
- Spring Quartz定时器源码 配置文件 多个触发器
- Spring Quartz定时器源码 配置文件 多个触发器
- Spring Quartz定时器源码 配置文件 多个触发器
- Quartz集群实战及原理解析
- Quartz集群配置与原理解析
- 并查集详解
- 纹理坐标处理
- 关于sessionid
- BroadcastReceiver与自定义权限
- Linux搭建Nginx环境
- Quartz源码解析 ---- 触发器按时启动原理
- SIGBUS 和 SIGSEGV
- 为您的Android,iOS等应用添加声波传输功能
- javascript知识点
- VS编译duilib项目时候的错误解决方法整理
- The issue : R cannot be resolved to a variable
- seajs学习笔记
- eclipse+ADT 进行android应用签名打包详解
- CocoaPods一个Objective-C第三方库的管理利器