CyclicBarrier无法按预期工作

时间:2013-12-20 18:02:37

标签: java concurrency cyclicbarrier

我正在尝试使用CyclicBarrier模拟一场triatlon比赛,但它没有按预期工作,我不知道为什么。

比赛的每个部分都必须等到所有选手都完成前一个比赛,但似乎它永远等待。

这是第一阶段的代码:

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 个答案:

答案 0 :(得分:5)

你有一个错误:你为100个线程创建一个CyclicBarrier,但执行101 await s,一次性在main方法中。由于循环障碍的语义,并且受到非确定性条件的影响,您的主线程将是最后一个执行await的线程,因此不会等待另外99个线程加入。

解决此问题后,即使完成所有工作,您也会发现应用程序仍在运行。这是因为你没有调用e.shutdown(),因此在主线程完成后,池中的所有线程都保持活动状态。

BTW getNumberWaiting总是为我显示0,这是因为100个提交的线程到达屏障后屏障降低后的预期值。然而,这是不确定的,并且可能随时改变。

答案 1 :(得分:2)

一旦所有各方都呼叫等待并且障碍被打开,

CyclicBarrier就会出现问题。由此得名。 因此,如果您使用5个参与方创建它,并且有6个呼叫await,则最后一个将触发它再次等待另外4个参与方加入。

这基本上就是这里发生的事情,因为你在主要节目中有1个额外的await电话。它正在等待另一个跑步者1号召唤。

简单的解决方法是使用跑步者+ 1方创建CyclicBarrier