2

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

2 回答 2

5

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

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

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

于 2013-12-20T18:32:18.413 回答
2

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

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

简单的解决方法是创建CyclicBarrier与 runners+1 派对。

于 2013-12-20T18:46:43.477 回答