2.算出下次触发的时间,比如是 09:10:00 ,减去当前时间 09:00:00 ,也就是还有10分钟才会触发下次任务。那就wait 10分钟
p.s. 最近刚好在看quartz的源码,还是比较容易看懂,建议你也好好看看
QuartzSchedulerThread.class
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) {
}
}
}
if(releaseIfScheduleChangedSignificantly(triggers, triggerTime)) {
break;
}
now = System.currentTimeMillis();
timeUntilTrigger = triggerTime - now;
}
从线程开始, 我们来看下QuartzSchedulerThread类(负责执行触发的Trigger的工作) :
使用了AtomicBoolean类halted.get()检查触发器是否是暂停状态, 早期版本的Quartz用的还是Boolean, AtomicBoolean类只有在值稳定后才会更新, 保持操作原子性。 从上面代码可以看出, 只要是触发器停止状态或者等待状态, Thread就会一直wait。sigLock同步对象用来随时唤醒将被触发的Trigger(使用notifyAll来进行对wait中线程的唤醒, 如下源码)
qsRsrcs.getThreadPool().blockForAvailableThreads() // 获取线程池现在可以用线程数
跟spring集成的配置(建议一般使用10~50个线程): 下面一行代码配置了最大线程数
接上面run方法代码:
availThreadCount必然大于0, 因为肯定至少得有一个线程来处理Trigger。
以上代码基本上做的就是以下轮询(服务器启动后不断地执行run方法):
qsRsrcs.getJobStore().acquireNextTriggers【查找即将触发的Trigger】 ---->
sigLock.wait(timeUntilTrigger)【等待执行】 ---->
qsRsrcs.getJobStore().triggersFired(triggers)【执行】---->
qsRsrcs.getJobStore().releaseAcquiredTrigger(triggers.get(i)) 【释放Trigger】