/** * Removes any tasks waiting to be run. Will not interrupt any tasks currently running if {@link * #tick(ExceptionHandlerInterface)} is being called. But will avoid additional tasks from being * run on the current {@link #tick(ExceptionHandlerInterface)} call. * * <p>If tasks are added concurrently during this invocation they may or may not be removed. * * @return List of runnables which were waiting in the task queue to be executed (and were now * removed) */ public List<Runnable> clearTasks() { List<TaskContainer> containers; synchronized (scheduledQueue.getModificationLock()) { containers = new ArrayList<TaskContainer>(executeQueue.size() + scheduledQueue.size()); Iterator<? extends TaskContainer> it = executeQueue.iterator(); while (it.hasNext()) { TaskContainer tc = it.next(); /* we must use executeQueue.remove(Object) instead of it.remove() * This is to assure it is atomically removed (without executing) */ if (!tc.running && executeQueue.remove(tc)) { int index = ListUtils.getInsertionEndIndex(containers, tc, true); containers.add(index, tc); } } it = scheduledQueue.iterator(); while (it.hasNext()) { TaskContainer tc = it.next(); if (!tc.running) { int index = ListUtils.getInsertionEndIndex(containers, tc, true); containers.add(index, tc); } } scheduledQueue.clear(); } return ContainerHelper.getContainedRunnables(containers); }
@Override public void runComplete() { synchronized (scheduledQueue.getModificationLock()) { ClockWrapper.stopForcingUpdate(); try { updateNextRunTime(); // almost certainly will be the first item in the queue int currentIndex = scheduledQueue.indexOf(this); if (currentIndex < 0) { // task was removed from queue, do not re-insert return; } long nextDelay = getDelayInMillis(); if (nextDelay < 0) { nextDelay = 0; } int insertionIndex = ListUtils.getInsertionEndIndex(scheduledQueue, nextDelay, true); scheduledQueue.reposition(currentIndex, insertionIndex); } finally { ClockWrapper.resumeForcingUpdate(); } } }
/** * Adds a task to scheduled/recurring queue. This call is more expensive than {@link * #addImmediateExecute(OneTimeTask)}, but is necessary for any tasks which are either delayed or * recurring. * * @param runnable Task to execute on next {@link #tick(ExceptionHandlerInterface)} call */ protected void addScheduled(TaskContainer runnable) { synchronized (scheduledQueue.getModificationLock()) { ClockWrapper.stopForcingUpdate(); try { int insertionIndex = ListUtils.getInsertionEndIndex(scheduledQueue, runnable, true); scheduledQueue.add(insertionIndex, runnable); } finally { ClockWrapper.resumeForcingUpdate(); } } notifyQueueUpdate(); }