线程(七)---CyclicBarrier

写在前面:各位看到此博客的小伙伴,如有不对的地方请及时通过私信我或者评论此博客的方式指出,以免误人子弟。多谢!

概念:

  CyclicBarrier允许一组线程在到达某个栅栏点(common barrier point)互相等待,直到最后一个线程到达栅栏点,栅栏才会打开,处于阻塞状态的线程恢复继续执行。通过CyclicBarrier的await()方法,线程就处于barrier状态。找到一张动图很好的说明了CyclicBarrier的执行过程。

常用构造方法:

1.public CyclicBarrier(int parties)

  初始化相互等待的线程数量。

2.public CyclicBarrier(int parties, Runnable barrierAction)

  初始化相互等待的线程数量以及屏障线程。

参数说明:

parties:表示一起执行的线程个数,例如:CyclicBarrier cyclicBarrier = new CyclicBarrier(3);于是拥有CyclicBarrier对象的线程当               parties的计数为3时就会唤醒,这里parties里的计数在运行时当调用CyclicBarrier:await()时,计数就加1,一直加到初始的值。

Runnable barrierAction:

表示线程都处于barrier时,一起执行之前,先执行的一个线程,即:屏障线程的运行时机:等待的线程数量=parties之后,CyclicBarrier打开屏障之前。这个参数是一个实现Runnable接口的类的对象 。

常用方法:

 await(): 在CyclicBarrier上进行阻塞等待,直到

        1): 在CyclicBarrier上等待的线程数达到parties,则所有线程释放,继续执行。

        2): 当前线程被中断,则抛出InterruptedException异常,并停止等待,继续执行。

        3): 其它等待的线程被中断,则当前线程抛出BrokenBarrierException异常,并停止等待,继续执行。

        4): 其它等待的线程超时,则当前线程抛出BrokenBarrierException异常,并停止等待,继续执行。

        5): 其它线程调用CyclicBarrier.reset()方法,则当前线程抛出BrokenBarrierException异常,并停止等待,继续执行。

await(timeout,TimeUnit): 在CyclicBarrier上进行限时的阻塞等待,直到

        1): 同上五条。

        2): 当前线程等待超时,则抛出TimeoutException异常,并停止等待,继续执行。

getParties(): 获取CyclicBarrier打开屏障的线程数量。

getNumberWaiting(): 获取正在CyclicBarrier上等待的线程数量。

reset(): 使得CyclicBarrier回归初始状态。

      1): 如果有正在等待的线程,则会抛出BrokenBarrierException异常,且这些线程停止等待,继续执行。
      2): 将是否破损标志位broken置为false。

isBroken(): 获取是否破损标志位broken的值,此值有以下几种情况:

     1): CyclicBarrier初始化时,broken=false,表示屏障未破损。

     2): 如果正在等待的线程被中断,则broken=true,表示屏障破损。

     3): 如果正在等待的线程超时,则broken=true,表示屏障破损。

     4): 如果有线程调用CyclicBarrier.reset()方法,则broken=false,表示屏障回到未破损状态。

场景:

1.以相约爬山为例,三个小伙伴都到了,然后再开始爬上。

2.以相约爬山为例,三个小伙伴都到了,然后一起喊了一声加油,然后再开始爬上。

场景一代码示例:

public class CyclicBarrierTest {

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();

        CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
        for (int i=0;i<3;i++){
            Task1 task1 = new Task1(cyclicBarrier);
            executorService.execute(task1);
        }
        // 关闭线程池
        executorService.shutdown();

    }

    static class Task1 implements Runnable{
        private CyclicBarrier cyclicBarrier;
        public Task1(CyclicBarrier cyclicBarrier){
            this.cyclicBarrier = cyclicBarrier;
        }
        @Override
        public void run() {
            try {
                System.out.println("小伙伴" + Thread.currentThread().getName() + ":到了");
                cyclicBarrier.await();
                System.out.println("开始爬山!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }


}

执行结果如下:

场景二代码示例:

public class CyclicBarrierTest {

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();

        CyclicBarrier cyclicBarrier1 = new CyclicBarrier(3, new Runnable() {
            @Override
            public void run() {
                System.out.println("加油!");
            }
        });
        for (int i=0;i<3;i++){
            Task1 task1 = new Task1(cyclicBarrier1);
            executorService.execute(task1);
        }
        // 关闭线程池
        executorService.shutdown();

    }

    static class Task1 implements Runnable{
        private CyclicBarrier cyclicBarrier;
        public Task1(CyclicBarrier cyclicBarrier){
            this.cyclicBarrier = cyclicBarrier;
        }
        @Override
        public void run() {
            try {
                System.out.println("小伙伴" + Thread.currentThread().getName() + ":到了");
                cyclicBarrier.await();
                System.out.println("开始爬山!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }


}

执行结果如下:

结合前面的CountDownLatch对比一下它们的区别:

1.CountDownLatch是线程组之间的等待,即一个(或多个)线程等待N个线程完成某件事情之后再执行;而CyclicBarrier则是线程组内的等待,即每个线程相互等待,即N个线程都被拦截之后,然后依次执行。
2.CountDownLatch是减计数方式,而CyclicBarrier是加计数方式。
3.CountDownLatch计数为0无法重置,而CyclicBarrier计数达到初始值,则可以重置。
4.CountDownLatch不可以复用,而CyclicBarrier可以复用。  

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值