Login | Register   
LinkedIn
Google+
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


Tip of the Day
Language: Java Language
Expertise: Beginner
May 2, 1999

Thread Timing

Question:
How can I determine the total time it takes for a set of threads to execute?

Answer:
When you time a set of threads, you generally want to know the time elapsed between when the first thread starts and the last thread finishes. When you time a single thread, all you have to do is record a timestamp before starting the thread and another timestamp after a call to join(). This timing includes the overhead of creating the thread and joining the thread. If you don't want to include these overheads, and want to time only the work executed, you have to do the timing inside the thread. The first timing method is not easily extended to timing multiple threads, but the second method is.

Using the second method, you can create a wrapper class that implements the Runnable interface and places timing calls in its run() method. The TimingWrapper class in the code listing does this. Simple timing calls will not suffice, however, because they will result in timing each individual thread, rather than a group of threads. To solve this problem, you can create a timer class, like ThreadTimer, that tracks the starting and stopping of threads before recording a timestamp.

ThreadTimer is kind of like the guy who starts a car race. First he tells the drivers to start their engines, and then he starts the race. The ThreadTimer start() method makes sure all the threads have been created, and when the last one "starts its engine," it records a beginning timestamp and tells all the threads they can start running. As the threads finish, they call the ThreadTimer stop() method, which counts the threads until the last one is done. At that point it records an ending timestamp and notifies the master timing thread, which should be waiting in waitForResult(), that the timing result is ready. ThreadTimer is designed to work with threads wrapped with TimingWrapper. The code listing demonstrates the timing approach by timing some threads that execute a dummy loop.

/***
 * This program shows how you can time a set of threads.  The main()
 * program demonstrates the timing classes by spawning and timing a
 * set of threads that just execute a dummy loop.
 ***/
public class ThreadTiming {

  /** Times a group of threads.  Works with TimingWrapper. */
  public static class ThreadTimer {
    private boolean __resultReady;
    private int __monitor[], __numThreads;
    private long __begin, __end;

    /** Creates a ThreadTimer that can time a given number of threads. */
    public ThreadTimer(int numThreads) {
      __monitor     = new int[1];
      __monitor[0]  = 0;
      __numThreads  = numThreads;
      __resultReady = false;
    }

    /** Starts the timer when all the threads are ready to start. */
    public void start() {
      synchronized(__monitor) {
        if(++__monitor[0] >= __numThreads) {
          __begin = System.currentTimeMillis();
          __monitor.notifyAll();
        } else {
          while(true) {
            try {
              __monitor.wait();
            } catch(InterruptedException e) {
              continue;
            }
            break;
          }
        }
      }
    }

    /** Stops the timer when the last thread is done. */
    public void stop() {
      synchronized(__monitor) {
        if(--__monitor[0] <= 0) {
          __end   = System.currentTimeMillis();
          synchronized(this) {
            __resultReady = true;
            notify();
          }
        }
      }
    }

    /** Calling thread waits until timing result is ready. */
    public synchronized void waitForResult() {
      while(!__resultReady) {
        try {
          wait();
        } catch(InterruptedException e) {
        }
      }
      __resultReady = false;
    }

    /** Returns elapsed time in milliseconds. */
    public long getElapsedTime() {
      return (__end - __begin);
    }
  }

  /** Wraps a thread so it can be timed with a group. */
  public static class TimingWrapper implements Runnable {
    private Runnable __runMe;
    private ThreadTimer __timer;

    public TimingWrapper(Runnable runMe, ThreadTimer timer) {
      __runMe   = runMe;
      __timer   = timer;
    }

    public void run() {
      // Note, this timing approach does not measure thread creation
      // and thread joining overhead.
      __timer.start();
      __runMe.run();
      __timer.stop();
    }
  }


  public static final int NUM_THREADS = 10;
  public static final int NUM_LOOPS   = 10000000;

  public static void main(String[] args) {
    int thread;
    ThreadTimer timer;

    timer = new ThreadTimer(NUM_THREADS);

    // Start a number of threads that iterate a dummy loop
    for(thread = 0; thread < NUM_THREADS; thread++)
      new Thread(new TimingWrapper(new Runnable() {
        public void run() {
          for(int i=0; i < NUM_LOOPS; i++);
        }
      }, timer)).start();

    timer.waitForResult();

    System.out.println("Elapsed Seconds: " +
                       ((double)timer.getElapsedTime())/1000.0);
  }

}
DevX Pro
 
Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap