Reputation: 6006
I have read Bloch's Item 69(Effective Java) and there was an example of Simple framework for timing execution which uses 3 CountDownLatch
for synchronization threads. Also Bloch says that this example can be rewritten using 1 CyclicBarrier
. I have tried to do this and get the next code:
public static long time(ExecutorService exec, int count) throws InterruptedException, BrokenBarrierException {
CyclicBarrier cyclicBarrier = new CyclicBarrier(count+1);
for (int i = 0; i < count; i++) {
exec.submit(new Worker(cyclicBarrier, i));
}
System.out.println("Start processing");
cyclicBarrier.await();
long time = System.nanoTime();
cyclicBarrier.await();
long elapsedTime = (System.nanoTime() - time)/1000;
System.out.println("FIN. ");
return elapsedTime;
}
private static class Worker implements Runnable {
final CyclicBarrier cyclicBarrier;
int workerNumber;
Worker(CyclicBarrier cyclicBarrier, int workerCount) {
this.cyclicBarrier = cyclicBarrier;
this.workerNumber = workerCount;
}
public void run() {
try {
cyclicBarrier.await();
work();
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
private void work() {
System.out.println("Worker " + workerNumber + " starts his job");
System.out.println("Worker " + workerNumber + " finishes his job");
}
}
But I think there is a problem here(in time
method): after first await
I try to measure time of start of threads' execution, so I want to measure this time BEFORE all another threads starts. There is no any guarantee that this(long time = System.nanoTime();
) instruction will execute before another threads start.
How can I achieve such functionality with CyclicBarrier? Any suggestions?
Upvotes: 2
Views: 605
Reputation: 242686
CyclicBarrier
allows you to define a barrier action to be executed after all threads reached the barrier but before they resumed execution. Use CyclicBarrier(int, Runnable)
to define it.
Obviously, in your case it's up to you to distinguish between executions of barrier action before doing work and after finishing it, something like this:
class TimingAction implements Runnable {
private boolean running;
private long start;
private long elapsed;
public void run() {
if (running) {
elapsed = System.nanoTime() - start;
running = false;
} else {
start = System.nanoTime();
running = true;
}
}
...
}
TimingAction timer = new TimingAction();
CyclicBarrier cyclicBarrier = new CyclicBarrier(count + 1, timer);
...
long elapsed = timer.getElapsed();
Upvotes: 3