循环屏障异常处理

时间:2015-05-27 08:16:08

标签: java multithreading

我遇到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块中是否更好?

3 个答案:

答案 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用于同步事件。