2013-12-20 136 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