Как мне заставить java.concurrency.CyclicBarrier работать как положено

Я пишу код, который будет порождать два потока, а затем ждать их синхронизации, используя класс CyclicBarrier. Проблема заключается в том, что циклический барьер не работает должным образом, и основной поток не ожидает завершения отдельных потоков. Вот как выглядит мой код:

 class mythread extends Thread{
   CyclicBarrier barrier;
   public mythread(CyclicBarrier barrier) { 
       this.barrier = barrier;
      }

   public void run(){
            barrier.await();
       } 
 }



class MainClass{
 public void spawnAndWait(){
    CyclicBarrier barrier = new CyclicBarrier(2);
    mythread thread1 = new mythread(barrier).start();
    mythread thread2 = new mythread(barrier).start();
    System.out.println("Should wait till both threads finish executing before printing this");
  }
}

Есть идеи, что я делаю не так? Или есть лучший способ написать эти методы синхронизации барьера? Пожалуйста помоги.

4 ответа

Решение

Во время выполнения вашего основного потока вы создаете два других потока и говорите им ждать друг друга. Но вы ничего не написали, чтобы заставить ваш главный поток ждать их и жаловаться, что это не ждет. Пытаться

CyclicBarrier barrier = new CyclicBarrier(3);
mythread thread1 = new mythread(barrier).start();
mythread thread2 = new mythread(barrier).start();
barrier.await(); // now you wait for two new threads to reach the barrier.
System.out.println("Should wait till both threads finish executing before printing this");

КСТАТИ. Не расширяйте класс Thread, если это не нужно. Реализуйте Runnable и передайте реализации объектам Thread. Как это:

class MyRunnable implements Runnable {
    public void run(){
        // code to be done in thread
    }
}

Thread thread1 = new Thread(MyRunnable);
thread1.start();

РЕДАКТИРОВАТЬ
Обоснование для избежания расширения темы.
Эмпирическое правило - это как можно меньше связей. Наследование - это очень сильная связь между классами. Вы должны наследовать от Thread, если хотите изменить некоторые из его поведений по умолчанию (то есть переопределить некоторые методы) или хотите получить доступ к некоторым защищенным полям класса Thread. Если вы не хотите этого, вы выбираете более слабую связь - реализует Runnable и передает его в качестве параметра конструктора в экземпляр Thread.

Вы ищете метод Thread.join()...

thread1.join();
thread2.join();
System.out.println("Finished");

РЕДАКТИРОВАТЬ: из-за комментариев...

И если вы не хотите ждать вечно, вы также можете указать максимальное количество миллисекунд плюс наносекунд, чтобы дождаться окончания потока

Пройти Runnable экземпляр конструктора вашего CyclicBarrier как это.

CyclicBarrier barrier = new CyclicBarrier(2, new Runnable() {

    @Override
    public void run() {
        System.out.println("Should wait till both threads finish executing before printing this");
    }
});

new mythread(barrier).start();
new mythread(barrier).start();

Циклический барьер не является правильным выбором в этом случае. Вы должны использовать CountDownLatch Вот.

Я полагаю, что вы вызываете spawnAndWait метод из основного метода.

Причина этого не в том, что CyclicBarrier имеет 2 конструктора. Для выполнения постопераций вы должны использовать двухпараметрический конструктор. Главное помнить, что основной поток не будет ждать await Способ; но продолжу исполнять. Однако Тема, указанная в CyclicBarrier конструктор будет работать только тогда, когда все порожденные потоки останавливаются на барьере (await метод)

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