Development Class Java

/*
 * Copyright (c) 2004 David Flanagan.  All rights reserved.
 * This code is from the book Java Examples in a Nutshell, 3nd Edition.
 * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
 * You may study, use, and modify it for any non-commercial purpose,
 * including teaching and use in open-source projects.
 * You may distribute it non-commercially as long as you retain this notice.
 * For a commercial use license, or to purchase the book, 
 * please visit http://www.davidflanagan.com/javaexamples3.
 */
import java.util.Comparator;
import java.util.Date;
import java.util.SortedSet;
import java.util.TreeSet;
abstract class TimerTask implements Runnable {
  boolean cancelled = false; // Has it been cancelled?
  long nextTime = -1; // When is it next scheduled?
  long period; // What is the execution interval
  boolean fixedRate; // Fixed-rate execution?
  protected TimerTask() {
  }
  /**
   * Cancel the execution of the task. Return true if it was actually running,
   * or false if it was already cancelled or never scheduled.
   */
  public boolean cancel() {
    if (cancelled)
      return false; // Already cancelled;
    cancelled = true; // Cancel it
    if (nextTime == -1)
      return false; // Never scheduled;
    return true;
  }
  /**
   * When it the timer scheduled to execute? The run() method can use this to
   * see whether it was invoked when it was supposed to be
   */
  public long scheduledExecutionTime() {
    return nextTime;
  }
  /**
   * Subclasses must override this to provide that code that is to be run. The
   * Timer class will invoke this from its internal thread.
   */
  public abstract void run();
  // This method is used by Timer to tell the Task how it is scheduled.
  void schedule(long nextTime, long period, boolean fixedRate) {
    this.nextTime = nextTime;
    this.period = period;
    this.fixedRate = fixedRate;
  }
  // This will be called by Timer after Timer calls the run method.
  boolean reschedule() {
    if (period == 0 || cancelled)
      return false; // Don't run it again
    if (fixedRate)
      nextTime += period;
    else
      nextTime = System.currentTimeMillis() + period;
    return true;
  }
}
/**
 * This class is a simple implementation of the Java 1.3 java.util.Timer API
 */
public class Timer {
  // This sorted set stores the tasks that this Timer is responsible for.
  // It uses a comparator to sort the tasks by scheduled execution time.
  SortedSet tasks = new TreeSet(new Comparator() {
    public int compare(Object a, Object b) {
      return (int) (((TimerTask) a).nextTime - ((TimerTask) b).nextTime);
    }
    public boolean equals(Object o) {
      return this == o;
    }
  });
  // This is the thread the timer uses to execute the tasks.
  // The TimerThread class is defined below.
  TimerThread timer;
  /** This constructor create a Timer that does not use a daemon thread */
  public Timer() {
    this(false);
  }
  /** The main constructor: the internal thread is a daemon if specified */
  public Timer(boolean isDaemon) {
    timer = new TimerThread(isDaemon); // TimerThread is defined below
    timer.start(); // Start the thread running
  }
  /** Stop the timer thread, and discard all scheduled tasks */
  public void cancel() {
    synchronized (tasks) { // Only one thread at a time!
      timer.pleaseStop(); // Set a flag asking the thread to stop
      tasks.clear(); // Discard all tasks
      tasks.notify(); // Wake up the thread if it is in wait().
    }
  }
  /** Schedule a single execution after delay milliseconds */
  public void schedule(TimerTask task, long delay) {
    task.schedule(System.currentTimeMillis() + delay, 0, false);
    schedule(task);
  }
  /** Schedule a single execution at the specified time */
  public void schedule(TimerTask task, Date time) {
    task.schedule(time.getTime(), 0, false);
    schedule(task);
  }
  /** Schedule a periodic execution starting at the specified time */
  public void schedule(TimerTask task, Date firstTime, long period) {
    task.schedule(firstTime.getTime(), period, false);
    schedule(task);
  }
  /** Schedule a periodic execution starting after the specified delay */
  public void schedule(TimerTask task, long delay, long period) {
    task.schedule(System.currentTimeMillis() + delay, period, false);
    schedule(task);
  }
  /**
   * Schedule a periodic execution starting after the specified delay. Schedule
   * fixed-rate executions period ms after the start of the last. Instead of
   * fixed-interval executions measured from the end of the last.
   */
  public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
    task.schedule(System.currentTimeMillis() + delay, period, true);
    schedule(task);
  }
  /** Schedule a periodic execution starting after the specified time */
  public void scheduleAtFixedRate(TimerTask task, Date firstTime, long period) {
    task.schedule(firstTime.getTime(), period, true);
    schedule(task);
  }
  // This internal method adds a task to the sorted set of tasks
  void schedule(TimerTask task) {
    synchronized (tasks) { // Only one thread can modify tasks at a time!
      tasks.add(task); // Add the task to the sorted set of tasks
      tasks.notify(); // Wake up the thread if it is waiting
    }
  }
  /**
   * This inner class defines the thread that runs each of the tasks at their
   * scheduled times
   */
  class TimerThread extends Thread {
    // This flag is will be set true to tell the thread to stop running.
    // Note that it is declared volatile, which means that it may be
    // changed asynchronously by another thread, so threads must always
    // read its current value, and not used a cached version.
    volatile boolean stopped = false;
    // The constructor
    TimerThread(boolean isDaemon) {
      setDaemon(isDaemon);
    }
    // Ask the thread to stop by setting the flag above
    void pleaseStop() {
      stopped = true;
    }
    // This is the body of the thread
    public void run() {
      TimerTask readyToRun = null; // Is there a task to run right now?
      // The thread loops until the stopped flag is set to true.
      while (!stopped) {
        // If there is a task that is ready to run, then run it!
        if (readyToRun != null) {
          if (readyToRun.cancelled) { // If it was cancelled, skip.
            readyToRun = null;
            continue;
          }
          // Run the task.
          readyToRun.run();
          // Ask it to reschedule itself, and if it wants to run
          // again, then insert it back into the set of tasks.
          if (readyToRun.reschedule())
            schedule(readyToRun);
          // We've run it, so there is nothing to run now
          readyToRun = null;
          // Go back to top of the loop to see if we've been stopped
          continue;
        }
        // Now acquire a lock on the set of tasks
        synchronized (tasks) {
          long timeout; // how many ms 'till the next execution?
          if (tasks.isEmpty()) { // If there aren't any tasks
            timeout = 0; // Wait 'till notified of a new task
          } else {
            // If there are scheduled tasks, then get the first one
            // Since the set is sorted, this is the next one.
            TimerTask t = (TimerTask) tasks.first();
            // How long 'till it is next run?
            timeout = t.nextTime - System.currentTimeMillis();
            // Check whether it needs to run now
            if (timeout <= 0) {
              readyToRun = t; // Save it as ready to run
              tasks.remove(t); // Remove it from the set
              // Break out of the synchronized section before
              // we run the task
              continue;
            }
          }
          // If we get here, there is nothing ready to run now,
          // so wait for time to run out, or wait 'till notify() is
          // called when something new is added to the set of tasks.
          try {
            tasks.wait(timeout);
          } catch (InterruptedException e) {
          }
          // When we wake up, go back up to the top of the while loop
        }
      }
    }
  }
  /** This inner class defines a test program */
  public static class Test {
    public static void main(String[] args) {
      final TimerTask t1 = new TimerTask() { // Task 1: print "boom"
        public void run() {
          System.out.println("boom");
        }
      };
      final TimerTask t2 = new TimerTask() { // Task 2: print "BOOM"
        public void run() {
          System.out.println("\tBOOM");
        }
      };
      final TimerTask t3 = new TimerTask() { // Task 3: cancel the tasks
        public void run() {
          t1.cancel();
          t2.cancel();
        }
      };
      // Create a timer, and schedule some tasks
      final Timer timer = new Timer();
      timer.schedule(t1, 0, 500); // boom every .5sec starting now
      timer.schedule(t2, 2000, 2000); // BOOM every 2s, starting in 2s
      timer.schedule(t3, 5000); // Stop them after 5 seconds
      // Schedule a final task: starting in 5 seconds, count
      // down from 5, then destroy the timer, which, since it is
      // the only remaining thread, will cause the program to exit.
      timer.scheduleAtFixedRate(new TimerTask() {
        public int times = 5;
        public void run() {
          System.out.println(times--);
          if (times == 0)
            timer.cancel();
        }
      }, 5000, 500);
    }
  }
}