我遇到Cyclic屏障问题,请查看下面的代码 -
MeetingPoint1.java
public class MeetingPoint1 implements Runnable{
@Override
public void run() {
System.out.println(" MeetingPoint1 one cleared... ");
}
}
MeetingPoint2.java
public class MeetingPoint2 implements Runnable{
@Override
public void run() {
System.out.println(" MeetingPoint Two cleared... ");
}
}
VehicalRunnable.java
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
* @author chouhan_r
*
*/
public class VehicleRunnable implements Runnable {
private CyclicBarrier barrier1;
private CyclicBarrier barrier2;
public VehicleRunnable(CyclicBarrier barrier1, CyclicBarrier barrier2) {
this.barrier1 = barrier1;
this.barrier2 = barrier2;
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() +" Waiting at Meeting Point 1");
if(Thread.currentThread().getName().equalsIgnoreCase("Car")){
throw new RuntimeException("something weird happened");
}
barrier1.await();
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() +" Waiting at Meeting Point 2");
barrier2.await();
} catch(BrokenBarrierException | RuntimeException | InterruptedException e){
e.printStackTrace();
}
}
}
CyclicBarrierMain.java
import java.util.concurrent.CyclicBarrier;
/**
* @author chouhan_r
*
*/
public class CyclicBarrierMain {
/**
* @param args
*/
public static void main(String[] args) {
MeetingPoint1 meetingPoint1 = new MeetingPoint1();
MeetingPoint2 meetingPoint2 = new MeetingPoint2();
CyclicBarrier barrier1 = new CyclicBarrier(3, meetingPoint1);
CyclicBarrier barrier2 = new CyclicBarrier(3, meetingPoint2);
VehicleRunnable car = new VehicleRunnable(barrier1, barrier2);
VehicleRunnable bike = new VehicleRunnable(barrier1, barrier2);
VehicleRunnable bus= new VehicleRunnable(barrier1, barrier2);
new Thread(car,"Car").start();
new Thread(bike,"Bike").start();
new Thread(bus,"Bus").start();
}
}
当线程抛出一些异常时,所有其他线程在barrier1处等待有没有办法运行等待线程直到barrier2?将barrier.await()方法放在finally块中是否更好?
答案 0 :(得分:1)
你正在用计数器3创建一个循环屏障。两个线程能够调用barrier1.await();并因此等待计数器为零,以便它们可以继续进行,但第三个线程无法调用barrier1.await(),因为您在调用barrier.await()之前已明确抛出异常。因此,计数器不会为零,所有其他线程将被卡在barrier1.await()。
如果你想让所有其他线程继续进行,你必须在抛出异常之前再次调用barrier.await(),而不是在这个块中。
if(Thread.currentThread().getName().equalsIgnoreCase("Car")){
barrier1.await(); // call here
throw new RuntimeException("something weird happened");
}
答案 1 :(得分:0)
理想情况下,您应该使用await的超时版本。如果其中一个线程被阻塞了很长时间;那么这就有机会让所有障碍退出。
try {
leader = barrier.await(10, TimeUnit.MILLISECONDS); // waits for 10 millis - throws exception if timed out or throws BarrierBrokenExcepion if Barrier is Broker
} catch (TimeoutException e) {
if (barrier.isBroken()) { //on timeout checks if barrier is broken and exits
System.out.println("BARRIER is broken "+Thread.currentThread().getName());
break;
}
} catch (BrokenBarrierException e){
e.printStackTrace();
break;
}
你也可以在错过障碍的线程上调用reset()/抛出异常。这将导致另外两个挂起线程上出现BarrierBrokenException。其余的是实施细节。
答案 2 :(得分:0)
你应该使用Latch或Semaphore代替Barrier。 Simply Barrier是同步多个线程,Latch用于同步事件。