devxlogo

How to Time a Set of Threads

How to Time a Set of Threads

hen you time a set of threads, you generally want to know thetime elapsed between when the first thread starts and the last threadfinishes. When you time a single thread, all you have to do is recorda timestamp before starting the thread and another timestamp after acall to join(). This timing includes the overhead of creating thethread and joining the thread. If you don’t want to include theseoverheads, and only want to time the work executed, you have todo the timing inside the thread. The first timing method is noteasily extended to timing multiple threads, but the second method is.

Using the second method, you can create a wrapper class thatimplements the Runnable interface and places timingcalls in its run() method. TheTimingWrapper class in the code listing does this.Simple timing calls will not suffice, however, because they willresult in timing each individual thread, rather than a group ofthreads. To solve this problem, you can create a timer class, likeThreadTimer, that tracks the starting and stopping ofthreads before recording a timestamp.

ThreadTimer is kind of like the guy who starts a carrace. First he tells the drivers to start their engines, and then hestarts the race. The ThreadTimer start()method makes sure all the threads have been created, and when the lastone “starts its engine,” it records a beginning timestamp and tellsall the threads they can start running. As the threads finish, theycall the ThreadTimer stop() method, whichcounts the threads until the last one is done. At that point itrecords an ending timestamp and notifies the master timing thread,which should be waiting in waitForResult(), thatthe timing result is ready. ThreadTimer is designed towork with threads wrapped with TimingWrapper. The codelisting demonstrates the timing approach by timing some threads thatexecute 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);  }}
devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist