📄 simpletrigger.java
字号:
* fired. * </p> */ public int getTimesTriggered() { return timesTriggered; } /** * <p> * Set the number of times the <code>SimpleTrigger</code> has already * fired. * </p> */ public void setTimesTriggered(int timesTriggered) { this.timesTriggered = timesTriggered; } protected boolean validateMisfireInstruction(int misfireInstruction) { if (misfireInstruction < MISFIRE_INSTRUCTION_SMART_POLICY) return false; if (misfireInstruction > MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT) return false; return true; } /** * <p> * Updates the <code>SimpleTrigger</code>'s state based on the * MISFIRE_INSTRUCTION_XXX that was selected when the <code>SimpleTrigger</code> * was created. * </p> * * <p> * If the misfire instruction is set to MISFIRE_INSTRUCTION_SMART_POLICY, * then the following scheme will be used: <br> * <ul> * <li>If the Repeat Count is <code>0</code>, then the instruction will * be interpreted as <code>MISFIRE_INSTRUCTION_FIRE_NOW</code>.</li> * <li>If the Repeat Count is <code>REPEAT_INDEFINITELY</code>, then * the instruction will be interpreted as <code>MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT</code>. * <b>WARNING:</b> using MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT * with a trigger that has a non-null end-time may cause the trigger to * never fire again if the end-time arrived during the misfire time span. * </li> * <li>If the Repeat Count is <code>> 0</code>, then the instruction * will be interpreted as <code>MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT</code>. * </li> * </ul> * </p> */ public void updateAfterMisfire(Calendar cal) { int instr = getMisfireInstruction(); if (instr == Trigger.MISFIRE_INSTRUCTION_SMART_POLICY) { if (getRepeatCount() == 0) instr = MISFIRE_INSTRUCTION_FIRE_NOW; else if (getRepeatCount() == REPEAT_INDEFINITELY) instr = MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT; else // if (getRepeatCount() > 0) instr = MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT; } else if (instr == MISFIRE_INSTRUCTION_FIRE_NOW && getRepeatCount() != 0) instr = MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT; if (instr == MISFIRE_INSTRUCTION_FIRE_NOW) { setNextFireTime(new Date()); } else if (instr == MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT) { Date newFireTime = getFireTimeAfter(new Date()); while (newFireTime != null && cal != null && !cal.isTimeIncluded(newFireTime.getTime())) { newFireTime = getFireTimeAfter(newFireTime); } setNextFireTime(newFireTime); } else if (instr == MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT) { Date newFireTime = getFireTimeAfter(new Date()); while (newFireTime != null && cal != null && !cal.isTimeIncluded(newFireTime.getTime())) { newFireTime = getFireTimeAfter(newFireTime); } if (newFireTime != null) { int timesMissed = computeNumTimesFiredBetween(nextFireTime, newFireTime); setTimesTriggered(getTimesTriggered() + timesMissed); } setNextFireTime(newFireTime); } else if (instr == MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT) { Date newFireTime = new Date(); if (repeatCount != 0 && repeatCount != REPEAT_INDEFINITELY) { setRepeatCount(getRepeatCount() - getTimesTriggered()); setTimesTriggered(0); } setStartTime(newFireTime); setNextFireTime(newFireTime); } else if (instr == MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT) { Date newFireTime = new Date(); int timesMissed = computeNumTimesFiredBetween(nextFireTime, newFireTime); if (repeatCount != 0 && repeatCount != REPEAT_INDEFINITELY) { int remainingCount = getRepeatCount() - (getTimesTriggered() + timesMissed); if (remainingCount <= 0) { remainingCount = 0; } setRepeatCount(remainingCount); setTimesTriggered(0); } if(getEndTime() != null && getEndTime().before(newFireTime)) setEndTime(new Date(newFireTime.getTime() + 50)); setStartTime(newFireTime); setNextFireTime(newFireTime); } } /** * <p> * Called when the <code>{@link Scheduler}</code> has decided to 'fire' * the trigger (execute the associated <code>Job</code>), in order to * give the <code>Trigger</code> a chance to update itself for its next * triggering (if any). * </p> * * @see #executionComplete(JobExecutionContext, JobExecutionException) */ public void triggered(Calendar calendar) { timesTriggered++; previousFireTime = nextFireTime; nextFireTime = getFireTimeAfter(nextFireTime); while (nextFireTime != null && calendar != null && !calendar.isTimeIncluded(nextFireTime.getTime())) { nextFireTime = getFireTimeAfter(nextFireTime); } } /** * * @see org.quartz.Trigger#updateWithNewCalendar(org.quartz.Calendar, long) */ public void updateWithNewCalendar(Calendar calendar, long misfireThreshold) { nextFireTime = getFireTimeAfter(previousFireTime); Date now = new Date(); do { while (nextFireTime != null && calendar != null && !calendar.isTimeIncluded(nextFireTime.getTime())) { nextFireTime = getFireTimeAfter(nextFireTime); } if(nextFireTime != null && nextFireTime.before(now)) { long diff = now.getTime() - nextFireTime.getTime(); if(diff >= misfireThreshold) { nextFireTime = getFireTimeAfter(nextFireTime); continue; } } }while(false); } /** * <p> * Called by the scheduler at the time a <code>Trigger</code> is first * added to the scheduler, in order to have the <code>Trigger</code> * compute its first fire time, based on any associated calendar. * </p> * * <p> * After this method has been called, <code>getNextFireTime()</code> * should return a valid answer. * </p> * * @return the first time at which the <code>Trigger</code> will be fired * by the scheduler, which is also the same value <code>getNextFireTime()</code> * will return (until after the first firing of the <code>Trigger</code>). * </p> */ public Date computeFirstFireTime(Calendar calendar) { nextFireTime = getStartTime(); while (nextFireTime != null && calendar != null && !calendar.isTimeIncluded(nextFireTime.getTime())) { nextFireTime = getFireTimeAfter(nextFireTime); } return nextFireTime; } /** * <p> * Called after the <code>{@link Scheduler}</code> has executed the * <code>{@link org.quartz.JobDetail}</code> associated with the <code>Trigger</code> * in order to get the final instruction code from the trigger. * </p> * * @param context * is the <code>JobExecutionContext</code> that was used by the * <code>Job</code>'s<code>execute(xx)</code> method. * @param result * is the <code>JobExecutionException</code> thrown by the * <code>Job</code>, if any (may be null). * @return one of the Trigger.INSTRUCTION_XXX constants. * * @see #INSTRUCTION_NOOP * @see #INSTRUCTION_RE_EXECUTE_JOB * @see #INSTRUCTION_DELETE_TRIGGER * @see #INSTRUCTION_SET_TRIGGER_COMPLETE * @see #triggered(Calendar) */ public int executionComplete(JobExecutionContext context, JobExecutionException result) { if (result != null && result.refireImmediately()) return INSTRUCTION_RE_EXECUTE_JOB; if (result != null && result.unscheduleFiringTrigger()) return INSTRUCTION_SET_TRIGGER_COMPLETE; if (result != null && result.unscheduleAllTriggers()) return INSTRUCTION_SET_ALL_JOB_TRIGGERS_COMPLETE; if (!mayFireAgain()) return INSTRUCTION_DELETE_TRIGGER; return INSTRUCTION_NOOP; } /** * <p> * Returns the next time at which the <code>SimpleTrigger</code> will * fire. If the trigger will not fire again, <code>null</code> will be * returned. The value returned is not guaranteed to be valid until after * the <code>Trigger</code> has been added to the scheduler. * </p> */ public Date getNextFireTime() { return nextFireTime; } /** * <p> * Returns the previous time at which the <code>SimpleTrigger</code> will * fire. If the trigger has not yet fired, <code>null</code> will be * returned. */ public Date getPreviousFireTime() { return previousFireTime; } /** * <p> * Set the next time at which the <code>SimpleTrigger</code> should fire. * </p> * * <p> * <b>This method should not be invoked by client code.</b> * </p> */ public void setNextFireTime(Date nextFireTime) { this.nextFireTime = nextFireTime; } /** * <p> * Set the previous time at which the <code>SimpleTrigger</code> fired. * </p> * * <p> * <b>This method should not be invoked by client code.</b> * </p> */ public void setPreviousFireTime(Date previousFireTime) { this.previousFireTime = previousFireTime; } /** * <p> * Returns the next time at which the <code>SimpleTrigger</code> will * fire, after the given time. If the trigger will not fire after the given * time, <code>null</code> will be returned. * </p> */ public Date getFireTimeAfter(Date afterTime) { if (complete) return null; if ((timesTriggered > repeatCount) && (repeatCount != REPEAT_INDEFINITELY)) return null; if (afterTime == null) afterTime = new Date(); if (repeatCount == 0 && afterTime.compareTo(getStartTime()) >= 0) return null; long startMillis = getStartTime().getTime(); long afterMillis = afterTime.getTime(); long endMillis = (getEndTime() == null) ? Long.MAX_VALUE : getEndTime() .getTime(); if (endMillis <= afterMillis) return null; if (startMillis < afterMillis && repeatCount == 0) return null; if (afterMillis < startMillis) return new Date(startMillis); long numberoftimesexecutedplusone = ((afterMillis - startMillis) / repeatInterval) + 1; if ((numberoftimesexecutedplusone > repeatCount) && (repeatCount != REPEAT_INDEFINITELY)) return null; Date time = new Date((numberoftimesexecutedplusone * repeatInterval) + startMillis); if (endMillis <= time.getTime()) return null; return time; } /** * <p> * Returns the last time at which the <code>SimpleTrigger</code> will * fire, before the given time. If the trigger will not fire before the * given time, <code>null</code> will be returned. * </p> */ public Date getFireTimeBefore(Date end) { if (end.getTime() < getStartTime().getTime()) return null; int numFires = computeNumTimesFiredBetween(getStartTime(), end); return new Date(getStartTime().getTime() + (numFires * repeatInterval)); } public int computeNumTimesFiredBetween(Date start, Date end) { long time = end.getTime() - start.getTime(); return (int) (time / repeatInterval); } /** * <p> * Returns the final time at which the <code>SimpleTrigger</code> will * fire, if repeatCount is REPEAT_INDEFINITELY, null will be returned. * </p> * * <p> * Note that the return time may be in the past. * </p> */ public Date getFinalFireTime() { if (repeatCount == 0) return startTime; if (repeatCount == REPEAT_INDEFINITELY && getEndTime() == null) return null; if (repeatCount == REPEAT_INDEFINITELY && getEndTime() == null) return null; else if (repeatCount == REPEAT_INDEFINITELY) return getFireTimeBefore(getEndTime()); long lastTrigger = startTime.getTime() + (repeatCount * repeatInterval); if ((getEndTime() == null) || (lastTrigger < getEndTime().getTime())) return new Date( lastTrigger); else return getFireTimeBefore(getEndTime()); } /** * <p> * Determines whether or not the <code>SimpleTrigger</code> will occur * again. * </p> */ public boolean mayFireAgain() { return (getNextFireTime() != null); } /** * <p> * Validates whether the properties of the <code>JobDetail</code> are * valid for submission into a <code>Scheduler</code>. * * @throws IllegalStateException * if a required property (such as Name, Group, Class) is not * set. */ public void validate() throws SchedulerException { super.validate(); if (repeatCount != 0 && repeatInterval < 1) throw new SchedulerException("Repeat Interval cannot be zero.", SchedulerException.ERR_CLIENT_ERROR); } public static void main(String[] args) // TODO: remove method after good // unit testing throws Exception { Date sdt = new Date(); Date edt = new Date(sdt.getTime() + 55000L); SimpleTrigger st = new SimpleTrigger("t", "g", "j", "g", sdt, edt, 10, 10000L); System.err.println(); st.computeFirstFireTime(null); System.err.println("lastTime=" + st.getFinalFireTime()); java.util.List times = TriggerUtils.computeFireTimes(st, null, 50); for (int i = 0; i < times.size(); i++) { System.err.println("firetime = " + times.get(i)); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -