/** * Terminates this timer, discarding any currently scheduled tasks. Does not interfere with a * currently executing task (if it exists). Once a timer has been terminated, its execution thread * terminates gracefully, and no more tasks may be scheduled on it. * * <p>Note that calling this method from within the run method of a timer task that was invoked by * this timer absolutely guarantees that the ongoing task execution is the last task execution * that will ever be performed by this timer. * * <p>This method may be called repeatedly; the second and subsequent calls have no effect. */ public void cancel() { synchronized (queue) { queue.newTasksMayBeScheduled = false; queue.clear(); queue.notify(); // In case queue was already empty. } }
/** * 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(); } }