Test Harness creates some threads that need to be started at the same time, then measure the time elapsed between the threads start and the last thread finish.
A CountDownLatch(1) is used as the start gate, the worker threads await() on this gate, while the main thread countDown() it to break the gate.
A CountDownLatch(nThreads) is used as the end gate, each worker thread countDown() it, while the main thread await() on this gate to tell when the last thread finish its work.
Notice that TestHarness's state variables startGate and endGate are published safely with final keyword, and the CountDownLatch class is thread safe.
import java.util.concurrent.CountDownLatch;
public class TestHarness {
public long timeTasks(int nThreads, final Runnable task)
throws InterruptedException {
final CountDownLatch startGate = new CountDownLatch(1);
final CountDownLatch endGate = new CountDownLatch(nThreads);
for (int i = 0; i < nThreads; i++) {
Thread t = new Thread() {
public void run() {
try {
startGate.await();
try {
task.run();
} finally {
endGate.countDown();
}
} catch (InterruptedException ignored) {
}
}
};
t.start();
}
long start = System.nanoTime();
startGate.countDown();
endGate.await();
long end = System.nanoTime();
return end - start;
}
public static void main(String[] args) throws InterruptedException {
TestHarness t = new TestHarness();
long elaspse = t.timeTasks(10, new Runnable() {
@Override
public void run() {
for(int i = 0; i < 10000; i++) {
//waste of time
}
}});
System.out.println(elaspse);
}
}