Как мне заставить 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
метод)