A simple implementation of the Java 1.3 java.util.Timer API : Timer « Development Class « Java






A simple implementation of the Java 1.3 java.util.Timer API

     

/*
 * 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);
    }
  }
}

   
    
    
    
    
  








Related examples in the same category

1.Timer Skipping BeepTimer Skipping Beep
2.Timer Schedule a task that executes once every secondTimer Schedule a task that executes once every second
3.Use java.util.Timer to schedule a task to execute once 5 seconds have passedUse java.util.Timer to schedule a task to execute once 5 seconds have passed
4.Timer utilities
5.Timer and TimerTask Classes
6.Pause and start a timer task
7.Create a Timer object
8.Swing also provide a Timer class. A Timer object will send an ActionEvent to the registered ActionListener.
9.Schedule a task by using Timer and TimerTask.
10.Scheduling a Timer Task to Run Repeatedly
11.Create a scheduled task using timer
12.extends TimerTask to create your own task
13.Scheduling a Timer Task to Run at a Certain Time
14.Class encapsulating timer functionality
15.Timeout Observer
16.A pool of objects that should only be used by one thread at a time
17.A class that allows a programmer to determine the amount of time spend doing certain routines
18.All times in this Timer object are in milliseconds. The timer starts from the moment of it's creation.
19.Thread Timer
20.Cancel Aware Timer
21.HRTimer is a simple system-wide timer facility using a singleton Timer, with additional instrumentation.
22.Used for timing events with millisecond precision.
23.A class to wait until a condition becomes true.