Java 自行车运载器未按预期工作

Java 自行车运载器未按预期工作,java,concurrency,cyclicbarrier,Java,Concurrency,Cyclicbarrier,我正在尝试使用CyclicBarrier模拟一场triatlon比赛,但它没有达到预期效果,我不知道为什么 比赛的每一部分都要等到所有的参赛者都完成了前一部分,但这似乎是永远的等待 这是第一阶段的代码: class Runner implements Runnable { private CyclicBarrier bar = null; private static int runners; private static double[] time; priva

我正在尝试使用
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
}
}
类运行程序实现可运行
{
专用循环载波条=null;
私家车;
私有静态双[]时间;
私有整数;
公共静态字符串名;
公共运行程序(int运行程序,字符串名称)
{
时间=新的双人[跑步者];

对于(int i=0;i您有一个off by one错误:您为100个线程创建了一个
CyclicBarrier
,但执行101个
await
s,这个一次性方法在main方法中。由于循环屏障的语义,并且受不确定条件的影响,您的主线程将是最后一个执行
await
的线程,因此留下一个错误。)孤独地等待另外99个线程加入

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


顺便说一句,getNumberWaiting
始终为我显示0,这是由于100个提交的线程到达屏障而降低屏障后的预期值。但是,这是不确定的,并且可以随时更改。

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

这基本上就是这里发生的事情,因为你在你的main中有一个额外的
wait
调用。它正在等待另一个runner-1调用发生


简单的解决方法是创建
CyclicBarrier
和runners+1个团队。

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