2013-12-20 191 views
2

我想模擬使用CyclicBarrier的triatlon競爭,但它沒有按預期工作,我不知道爲什麼。CyclicBarrier不按預期工作

比賽的每一部分都要等到所有的跑步者都完成了前一個跑步者,但看起來好像是在等待着。

這是第一階段的一段代碼:

class Runner implements Runnable 
{ 
    private CyclicBarrier bar = null; 
    private static int runners; 
    private static double[] time; 
    private int number; 
    public static String name; 

    public Runner(int runners, String name) 
    { 
     time = new double[runners]; 
     for (int i=0; i<runners; i++) 
      time[i] = 0; 
     this.name= name; 
    } 

    public Runner(CyclicBarrier bar, int number) 
    { 
     this.bar = bar; 
     this.number = number; 
    } 

    public void run() 
    { 
     try { int i = bar.await(); } 
        catch(InterruptedException e) {} 
         catch (BrokenBarrierException e) {} 
     double tIni = System.nanoTime(); 
     try { Thread.sleep((int)(100*Math.random()); } catch(InterruptedException e) {} 
     double t = System.nanoTime() - tIni; 
     time[number] += t; 
    } 
} 

public class Triatlon 
{ 
public static void main(String[] args) 
{ 
    int runners = 100; 
    CyclicBarrier Finish_Line_1 = new CyclicBarrier (runners); 

    Runner c = new Runner(runners, "Triatlon"); 

    ExecutorService e = Executors.newFixedThreadPool(runners); 

    for (int i=0; i<runners; i++) 
     e.submit(new Runner(Finish_Line_1, i)); 

    System.out.println(Finish_Line_1.getNumberWaiting()); // this always shows 99 
    try { int i = Finish_Line_1.await(); } 
      catch(InterruptedException e01) {} 
      catch (BrokenBarrierException e02) {} 
    System.out.println("Swimming phase completed"); 

     // here the rest of the competition, which works the same way 
} 
} 

回答

2

CyclicBarrier週期一旦所有各方都呼籲等待和屏障打開。由此得名。 所以,如果你創建5方,並有6個電話await最後一個會觸發它再次等待4個多方加入。

這基本上就是這裏發生的事情,因爲您在主服務器中有一個額外的await呼叫。它正在等待另一名跑步者1的呼叫發生。

簡單的修復方法是創建CyclicBarrier跑步者+ 1派對。

5

您有一個差一錯誤:你創建一個CyclicBarrier爲100個線程,但執行101 await秒,一次性在主要方法。由於循環障礙的語義,並受到非確定性條件的限制,因此您的主線程將是最後執行的await,因此無需等待另外99個線程加入。

修復此問題後,您即使在所有工作完成後,應用程序仍會繼續運行。這是因爲您沒有調用e.shutdown(),所以在主線程完成後,池中的所有線程都保持活動狀態。

順便說一句getNumberWaiting對我來說總是顯示0,這是因爲100個提交的線程到達屏障而降低屏障後的期望值。然而,這是不確定的,並且可以在任何時候改變。

+0

你明白了。我想補充一點,我認爲它應該是'Thread.sleep(...)'然後'barrier.await()'在每個運行方法中。事實上,跑步者跑步,然後等待其他人加入 – Grooveek

+0

@Grooveek這會更有意義,是的 - 並且會掩蓋OP的錯誤,因爲然後池中的一個線程會卡住。根據代碼的其餘部分,錯誤可能會在下一個階段中出現,並且起源更加混亂。 –

+0

謝謝!這給我的問題提供了一個解決方案。雖然我看到一個異常。印刷完「游泳階段完成」後,程序沒有完成,就好像它正在等待其他事情發生一樣。 – dabadaba