/** * */ package com.vip.saturn.job.trigger; import java.util.Date; import java.util.concurrent.atomic.AtomicBoolean; import org.quartz.SchedulerException; import org.quartz.Trigger; import org.quartz.spi.OperableTrigger; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.vip.saturn.job.basic.AbstractElasticJob; import com.vip.saturn.job.basic.SaturnConstant; /** * @author chembo.huang * */ public class SaturnWorker implements Runnable { static Logger log = LoggerFactory.getLogger(SaturnWorker.class); private AbstractElasticJob job; private OperableTrigger triggerObj; private final Object sigLock = new Object(); private boolean paused = false; private boolean triggered = false; private AtomicBoolean halted = new AtomicBoolean(false); public SaturnWorker(AbstractElasticJob job, Trigger trigger) throws SchedulerException { this.job = job; initTrigger(trigger); } public void reInitTrigger(Trigger trigger) throws SchedulerException { initTrigger(trigger); synchronized (sigLock) { sigLock.notifyAll(); } } private void initTrigger(Trigger trigger) throws SchedulerException { if(trigger == null) return; this.triggerObj = (OperableTrigger) trigger; Date ft = this.triggerObj.computeFirstFireTime(null); if (ft == null) { log.warn("[{}] msg=Based on configured schedule, the given trigger '" + trigger.getKey() + "' will never fire.", job.getJobName()); } } public boolean isShutDown() { return halted.get(); } void togglePause(boolean pause) { synchronized (sigLock) { paused = pause; sigLock.notifyAll(); } } void halt() { synchronized (sigLock) { halted.set(true); sigLock.notifyAll(); } } void trigger() { synchronized (sigLock) { triggered = true; sigLock.notifyAll(); } } @Override public void run() { while (!halted.get()) { try { synchronized (sigLock) { while (paused && !halted.get()) { try { sigLock.wait(1000L); } catch (InterruptedException ignore) { } } if (halted.get()) { break; } } boolean noFireTime = false; // 没有下次执行时间,初始化为false long timeUntilTrigger = 1000; if(triggerObj != null){ triggerObj.updateAfterMisfire(null); long now = System.currentTimeMillis(); Date nextFireTime = triggerObj.getNextFireTime(); if(nextFireTime != null) { timeUntilTrigger = nextFireTime.getTime() - now; } else { noFireTime = true; } } while (!noFireTime && timeUntilTrigger > 2) { synchronized (sigLock) { if (halted.get()) { break; } if (triggered){ break; } try { sigLock.wait(timeUntilTrigger); } catch (InterruptedException ignore) { } if(triggerObj != null){ long now = System.currentTimeMillis(); Date nextFireTime = triggerObj.getNextFireTime(); if(nextFireTime != null) { timeUntilTrigger = nextFireTime.getTime() - now; } else { noFireTime = true; } } } } boolean goAhead; // 触发执行只有两个条件:1.时间到了;2。点立即执行; synchronized (sigLock) { goAhead = !halted.get() && !paused; // 重置立即执行标志; if (triggered) { triggered = false; } else { // 非立即执行。即,执行时间到了,或者没有下次执行时间。 goAhead = goAhead && !noFireTime; if(goAhead && triggerObj != null) { // 执行时间到了,更新执行时间;没有下次执行时间,不更新时间,并且不执行作业 triggerObj.triggered(null); } } } if (goAhead) { job.execute(); } } catch (RuntimeException e) { log.error(String.format(SaturnConstant.ERROR_LOG_FORMAT, job.getJobName(), e.getMessage()), e); } } } }