Java高并发编程中CyclicBarrier的使用及详细介绍-刘宇

作者:刘宇
CSDN博客地址:https://blog.csdn.net/liuyu973971883
有部分资料参考,如有侵权,请联系删除。如有不正确的地方,烦请指正,谢谢。

一、什么是CyclicBarrier

“循环栅栏”,大概的意思就是一个可循环利用的屏障。它的作用就是会让所有线程都等待完成后才会继续下一步行动。打个比方,我们和好朋友约好出去吃饭的时候,有些人早到了,有些人晚到了,但是饭局要等到所有人都到了才能开始,且他们是相互监督的。我们可以把这些朋友看作一个线程。

二、CyclicBarrier的简单使用

1、构造方法

  • parties:一个任务需要被分为几个子任务,即我们上述举例中的有几个朋友。
  • barrierAction:所有子任务都完成后将会执行这个Runnable,即上述所说的吃饭
//构造函数1
public CyclicBarrier(int parties)
//构造函数2
public CyclicBarrier(int parties, Runnable barrierAction)

2、await()

  • 调用该方法后,表示该线程已到达栅栏,等待其他线程
public int await() throws InterruptedException, BrokenBarrierException

3、await(long timeout, TimeUnit unit)

  • 调用该方法后,表示该线程已到达栅栏,等待指定时间
  • timeout:等待指定时间,如果还有线程未到达栅栏,那么也不再等了
  • TimeUnit:时间单位
public int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException

4、getParties()

  • 获取该CyclicBarrier有几个部分,即初始化时候定义了几个部分
public int getParties()

5、isBroken()

  • 判断栅栏是否被打破
public boolean isBroken()

6、getNumberWaiting()

  • 获取当前await的线程有多少个
public int getNumberWaiting()

三、简单示例

package com.test.part3.CyclicBarrier;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;

public class CyclicBarrierExample {
    public static void main(String[] args) {
        final CyclicBarrier cyclicBarrier = new CyclicBarrier(2, new Runnable() {
            @Override
            public void run() {
                //当所有分支全部完成后回调
                System.out.println("All threads finished");
            }
        });
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    TimeUnit.SECONDS.sleep(10);
                    System.out.println("T1 finished work");
                    //等待其他前程完成,如果都完成了将自动唤醒
                    cyclicBarrier.await();
                    System.out.println("T1 The other thread finished too");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    TimeUnit.SECONDS.sleep(5);
                    System.out.println("T2 finished work");
                    //等待其他前程完成,如果都完成了将自动唤醒
                    cyclicBarrier.await();
                    System.out.println("T2 The other thread finished too");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

输出结果:

T2 finished work
T1 finished work
All threads finished
T1 The other thread finished too
T2 The other thread finished too

四、什么时候会出现BrokenBarrierException异常

  • 当我们调用reset方法对栅栏重新设置的时候就会出现BrokenBarrierException异常
package com.test.part3.CyclicBarrier;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;

public class CyclicBarrierExample2 {
    public static void main(String[] args) throws InterruptedException {
        final CyclicBarrier cyclicBarrier = new CyclicBarrier(2);
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                	//休眠5秒
                    TimeUnit.SECONDS.sleep(5);
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //立即await
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }

            }
        }).start();
        //休眠100毫秒
        TimeUnit.MILLISECONDS.sleep(100);
        //进行重置,那么进入await的线程就会抛出BrokenBarrierException异常
        cyclicBarrier.reset();
    }
}

输出结果:

java.util.concurrent.BrokenBarrierException
	at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250)
	at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362)
	at com.test.part3.CyclicBarrier.CyclicBarrierExample2$2.run(CyclicBarrierExample2.java:28)
	at java.lang.Thread.run(Thread.java:745)

五、CyclicBarrier和CountDownLatch的区别

他们都是可以实现当一组线程达到某个条件的时候再执行某些任务,是因为他们内部都有一个count计数器,当计数器为0时将所有阻塞的线程唤醒。

区别:

  • CyclicBarrier的await会将线程进行阻塞并且将count值减1,CountDownLatch的await只会将线程阻塞,计数器减1需要调用countdown来执行。
  • CyclicBarrier可以实现循环拦截,调用reset方法即可重置栅栏,而CountDownLatch只能拦截一次。
  • CyclicBarrier在等待多个线程到达某一条件时,他们是线程间相互监督的。CountDownLatch并不是线程间相互监督,而是有个类似于裁判的角色进行管理的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值