【问题标题】:CyclicBarrier not working as expectedCyclicBarrier 未按预期工作
【发布时间】:2013-12-20 18:02:36
【问题描述】:

我正在尝试使用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
}
}

【问题讨论】:

    标签: java concurrency cyclicbarrier


    【解决方案1】:

    你有一个逐一的错误:你为 100 个线程创建了一个 CyclicBarrier,但执行了 101 个 awaits,一次性在 main 方法中。由于循环屏障的语义,并且受非确定性条件的影响,您的主线程将是最后一个执行await,从而独自等待另外 99 个线程加入。

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

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

    【讨论】:

    • 你明白了。我要补充一点,我认为在每个运行方法中它应该是Thread.sleep(...) 然后是barrier.await()。事实上跑步者跑,然后等待其他人加入
    • @Grooveek 这更有意义,是的——并且会掩盖 OP 的错误,因为池中的一个线程会被卡住。根据代码的其余部分,错误可能会在下一个阶段冒泡,而且来源更加模糊。
    • 谢谢!这为我的问题提供了解决方案。我看到了一个异常。打印“游泳阶段完成”后,程序没有完成,就好像它在等待其他任何事情发生一样。
    • 你的 cmets 也让程序工作,但我不明白两件事:1)为什么它更有意义,因为在跑步者跑步之前放置障碍(Thread.sleep(...))意味着所有的跑者都准备好了,所以当障碍解除时,他们都一起开始比赛; 2)为什么这样做会掩盖错误?
    • 我猜跑步者 98 和 99 在第 2 阶段和第 3 阶段的问题正是因为你正在谈论的那个“卡住的线程”......老实说,我不知道如何放置解决办法。
    【解决方案2】:

    CyclicBarrier 在所有各方都调用 await 并打开屏障后循环。由此得名。 因此,如果您使用 5 个方创建它并且有 6 次调用 await,最后一个将触发它再次等待 4 个方加入。

    这基本上就是这里发生的事情,因为您的主程序中有 1 个额外的 await 调用。它正在等待另一个 runners-1 调用发生。

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

    【讨论】:

      猜你喜欢
      • 2021-06-04
      • 2022-01-24
      • 2015-05-11
      • 2020-05-15
      • 2014-10-31
      • 2018-02-12
      • 2014-01-20
      • 2015-01-13
      • 2013-08-01
      相关资源
      最近更新 更多