Java 多线程之CyclicBarrier

参考文章:http://www.jianshu.com/p/0c2af47f98fd

CyclicBarrier是同步辅助类,它允许一组线程相互等待,直到到达某个公共屏障点。

重要属性:

// 锁对象 lock
private final ReentrantLock lock = new ReentrantLock();
// trip 意思是 直到出错之前的条件 
private final Condition trip = lock.newCondition();
// 参与者
private final int parties;
// barrier将执行的任务或者命令
private final Runnable barrierCommand;
// generation对象。Generation是其内部类
private Generation generation = new Generation();
// 记录未到达屏障点的线程数量,count = 0表示全部达到
private int count;

注意:维护count 和parties是由于CyclicBarrier复用性决定的,reset方法即可复用。

构造参数:

//指定了参与者数量的CyclicBarrier
CyclicBarrier(int parties);
/** 
  * 指定了参与者数量,并且当参与者都到达屏障点时,优先执行任务barrierAction
  * 
  * /
CyclicBarrier(int parties, Runnable barrierAction);
// CyclicBarrier里面的内部类,它表示当前的CyclicBarrier是否是被损坏的。
// 默认broken为false是完整的。
private static class Generation {boolean broken = false;}	

重要方法:
1.nextGeneration()它里面有三个操作,

trip.signalAll();// 唤醒所有线程
// set up next generation
count = parties;
generation = new Generation(); // 重新生成Generation对象

2.breakBarrier() 破坏CyclicBarrier

generation.broken = true;
count = parties;
trip.signalAll();

方法1、2是在reset回环屏障的时候调用的方法!

3.await(),它的内部是调用dowait(false, 0L);这里表示 不超时限制。
dowait(boolean timed, long nanos)这里的参数是:对于是否超时,及超时的限制。

dowait的内部实现是:

final ReentrantLock lock = this.lock;//获取到了显示锁。
lock.lock();
try {
    final Generation g = generation; 获取CyclicBarrier的属性
	//如果 CyclicBarrier 已损坏,就抛出异常BrokenBarrierException
    if (g.broken)
        throw new BrokenBarrierException();
	//如果线程中断,破坏此CyclicBarrier并且抛出InterruptedException
    if (Thread.interrupted()) {
        breakBarrier();
        throw new InterruptedException();
    }
	// 指定线程数量--
   int index = --count;  
   // tripped   当index ==0 表示,所有指定的数目都已到达指定的公共屏障点
   if (index == 0) {  
       boolean ranAction = false;
       try {
           final Runnable command = barrierCommand;//把 barrierCommand属性赋给command
           if (command != null)  // 如果创建对象指定barrierAction,将执行run方法
               command.run();
           ranAction = true;
           nextGeneration();//执行完之后调用nextGeneration,更新CyclicBarrier状态,并且唤醒所有线程
           return 0;
       } finally {
           if (!ranAction) //如果 未成功完成上述try中的操作,ranAction为false则会破坏此CyclicBarrier
               breakBarrier();
       }
   }

    // loop until tripped, broken, interrupted, or timed out
    for (;;) {
        try {
            if (!timed)
                trip.await();
            else if (nanos > 0L)
                nanos = trip.awaitNanos(nanos);
        } catch (InterruptedException ie) {
            if (g == generation && ! g.broken) {
                breakBarrier();
                throw ie;
            } else {
                // We're about to finish waiting even if we had not
                // been interrupted, so this interrupt is deemed to
                // "belong" to subsequent execution.
                Thread.currentThread().interrupt();
            }
        }

        if (g.broken)
            throw new BrokenBarrierException();

        if (g != generation)
            return index;

        if (timed && nanos <= 0L) {
            breakBarrier();
            throw new TimeoutException();
        }
    }
} finally {
    lock.unlock();  // finally释放锁,这点要注意
}

案例一
CyclicBarrier运行下述有顺序的执行分步任务,这是一个CountDownlatch做不到的!

public class CyclicBarrierTest2 {

    private static CyclicBarrier cBarrier = null;

    public static void main(String[] args) throws InterruptedException {
        cBarrier = new CyclicBarrier(3);

        for(int i=0;i<3;i++){
            Thread party = new PartiesThread();
            party.start();
        }

        Thread.sleep(3000);
        System.out.println("正式开会...");
    }

    static class PartiesThread extends Thread{
        @SneakyThrows
        public void run(){
            System.out.println(Thread.currentThread().getName()+"到了会议室");
            cBarrier.await();
            System.out.println(Thread.currentThread().getName() + "找到座位");
            cBarrier.await();
            System.out.println(Thread.currentThread().getName() + "准备开会");
        }
    }

}

在这里插入图片描述
案例二
重置回环屏障

public class CyclicBarrierTest3 {

    private static CyclicBarrier cBarrier = null;

    public static void main(String[] args) {
        cBarrier = new CyclicBarrier(3, new Runnable() {
            @Override
            public void run() {
                System.out.println("-----------");
            }
        });

        for(int i=0;i<3;i++){
            Thread party = new PartiesThread();
            party.start();
            if (i == 2) {
                party.interrupt();
            }
        }

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        cBarrier.reset();

        for(int i=0;i<3;i++){
            Thread party = new PartiesThread();
            party.start();
        }

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        System.out.println("正式开会...");
    }

    static class PartiesThread extends Thread{
        @SneakyThrows
        public void run(){
            System.out.println(Thread.currentThread().getName()+"到了会议室");
            cBarrier.await();
            System.out.println(Thread.currentThread().getName() + "找到座位");
            cBarrier.await();
            System.out.println(Thread.currentThread().getName() + "准备开会");

        }
    }

}

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值