2012-09-13 22 views
2

我已閱讀Bloch的Item 69(Effective Java),並且有一個簡單的時序執行框架示例,它使用3 CountDownLatch作爲同步線程。布洛赫說,這個例子可以用1 CyclicBarrier來重寫。我試圖做到這一點,得到了下面的代碼:CyclicBarrier與CountDownLatch進行同步

 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"); 
     } 

    } 

但我認爲這裏有一個問題(在time法):第一await後,我試圖測量線程的執行開始的時間,所以我想要在所有其他線程開始之前測量這個時間。沒有任何保證這(long time = System.nanoTime();)指令將在另一個線程啓動之前執行。

如何使用CyclicBarrier實現此類功能?有什麼建議麼?

回答

3

CyclicBarrier允許您定義在所有線程到達屏障但在恢復執行之前要執行的屏障操作。使用CyclicBarrier(int, Runnable)來定義它。

顯然,在你的情況下,它是給你做工作之前和完成它,這樣的事情後阻擋作用的執行來區分:

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(); 
+0

偉大的解決方案!謝謝。此外,我最近了解到,我可以創建一個持有者類(又名可變長),並將其直接用於CyclicBarrier的匿名Runnable – maks