Esempio n. 1
0
  /** The main timer loop. (See class comment.) */
  private void mainLoop() {
    while (true) {
      try {
        TimerTask task;
        boolean taskFired;
        synchronized (queue) {
          // Wait for queue to become non-empty
          // But no more than timeout value.
          while (queue.isEmpty() && queue.newTasksMayBeScheduled) {
            queue.wait(THREAD_TIMEOUT);
            if (queue.isEmpty()) {
              break;
            }
          }
          if (queue.isEmpty()) break; // Queue is empty and will forever remain; die

          // Handle a possible change of the user clock
          queue.checkUserClockChange();

          // Queue nonempty; look at first evt and do the right thing
          long currentTime, executionTime;
          task = queue.getMin();
          synchronized (task.lock) {
            if (task.state == TimerTask.CANCELLED) {
              queue.removeMin();
              continue; // No action required, poll queue again
            }
            currentTime = Timer.monotonicTimeMillis();
            executionTime = task.nextExecutionTime;

            if (taskFired = (executionTime <= currentTime)) {
              if (task.period == 0) { // Non-repeating, remove
                queue.removeMin();
                task.state = TimerTask.EXECUTED;
              } else { // Repeating task, reschedule
                queue.rescheduleMin(
                    task.period < 0 ? currentTime - task.period : executionTime + task.period);
              }
            }
          }
          if (!taskFired) { // Task hasn't yet fired; wait
            long timeout = executionTime - currentTime;
            if (queue.hasUserClockTasks() && timeout > Timer.USER_CLOCK_CHECK_PERIOD) {
              timeout = Timer.USER_CLOCK_CHECK_PERIOD;
            }
            queue.wait(timeout);
          }
        }
        if (taskFired) { // Task fired; run it, holding no locks
          try {
            task.run();
          } catch (Exception e) {
            // Cancel tasks that cause exceptions
            task.cancel();
          }
        }
      } catch (InterruptedException e) {
      }
    }
  }
Esempio n. 2
0
  /**
   * 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();
    }
  }