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】






 

3 0
原创粉丝点击