CyclicBarrier не работает должным образом

Я пытаюсь смоделировать соревнования по триатлону, используя 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 партии, чтобы присоединиться.

Это в основном то, что здесь происходит, так как у вас есть 1 дополнительный await позвони в свою главную. Он ждет очередных звонков "Бегуны-1".

Простое решение заключается в создании CyclicBarrier с бегунами +1 партия.

У вас есть ошибка: вы создаете CyclicBarrier для 100 потоков, но выполнить 101 awaits, одноразовый в основном методе. Из-за семантики циклического барьера и с учетом недетерминированных условий ваш основной поток будет выполняться последним awaitтем самым оставаясь в одиночестве в ожидании присоединения еще 99 потоков.

После исправления этой проблемы вы обнаружите, что приложение продолжает работать даже после того, как вся работа выполнена. Это потому что ты не звонил e.shutdown(), так что все потоки в пуле остаются живыми после того, как основной поток сделан.

КСТАТИ getNumberWaiting всегда показывает 0 для меня, что является ожидаемым значением после того, как барьер был снижен из-за того, что 100 поданных потоков достигли его. Однако это недетерминировано и может измениться в любое время.

Другие вопросы по тегам