void checkUserClockChange() { if (!hasUserClockTasks()) { return; } final long userClockSkew = Timer.userClockSkew(); if (userClockSkew == 0) { return; } if (userClockSkew < 0) { for (int i = 1; i <= size; i++) { TimerTask task = queue[i]; if (task != null && task.isUserClock) { task.nextExecutionTime -= userClockSkew; fixUp(i); } } } else { for (int i = size; i >= 1; i--) { TimerTask task = queue[i]; if (task != null && task.isUserClock) { task.nextExecutionTime -= userClockSkew; fixDown(i); } } } }
/** * Sets the nextExecutionTime associated with the head task to the specified value, and adjusts * priority queue accordingly. * * @param newTime new time to apply to head task execution. */ void rescheduleMin(long newTime) { final TimerTask task = queue[1]; task.nextExecutionTime = newTime; fixDown(1); if (task.isUserClock) { // Only the first execution is scheduled against the user clock. // Subsequent executions are scheduled based on delays. task.isUserClock = false; userClockTaskRemoved(); } }
/** * Schedule the specified timer task for execution at the specified time with the specified * period, in milliseconds. If period is positive, the task is scheduled for repeated execution; * if period is zero, the task is scheduled for one-time execution. Time is specified in * Date.getTime() format. This method checks timer state, task state, and initial execution time, * but not period. * * @param task task to be scheduled. * @param userTime the user time at which task is to be executed or <tt>null</tt> if the delay is * specified * @param delay the delay in milliseconds before the task execution * @param period time in milliseconds between successive task executions. * @param isUserClock true if the time is bound to user clock * @throws IllegalArgumentException if <tt>time()</tt> is negative. * @throws IllegalStateException if task was already scheduled or cancelled, timer was cancelled, * or timer thread terminated. */ private void sched(TimerTask task, Date userTime, long delay, long period) { final boolean isUserClock = userTime != null; long time; if (isUserClock) { long t = userTime.getTime(); if (t < 0) { throw new IllegalArgumentException("Illegal execution time."); } time = Timer.userTimeFromStart(t); } else { time = Timer.monotonicTimeFromStart(JVM.monotonicTimeMillis() + delay); } synchronized (queue) { if (!queue.newTasksMayBeScheduled) { throw new IllegalStateException("Timer already cancelled."); } /* * If the TimerThread has exited without an error * it is restarted. See the commentary in TimerThread.run. */ if (thread == null || !thread.isAlive()) { thread = new TimerThread(queue); thread.start(); } synchronized (task.lock) { if (task.state != TimerTask.VIRGIN) { throw new IllegalStateException("Task already scheduled or cancelled"); } task.nextExecutionTime = time; task.period = period; task.state = TimerTask.SCHEDULED; task.isUserClock = isUserClock; } queue.add(task); if (queue.getMin() == task) queue.notify(); } }