前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >并发编程系列之CyclicBarrier用法简介

并发编程系列之CyclicBarrier用法简介

作者头像
SmileNicky
发布2021-11-30 19:16:41
5100
发布2021-11-30 19:16:41
举报
文章被收录于专栏:Nicky's blogNicky's blog

1、CyclicBarrier循环屏障定义

定义:协同指定数目的线程,让这些线程都在这个屏障前等待,直到所有的线程都到这个屏障前,再一起继续执行。线程执行完成后,这个屏障可以再次使用,因此被称之为循环屏障。

2、CyclicBarrier用法以及原理

  • 构造方法,CyclicBarrier(int parties):parties指定有多少个部分(线程)参与,称之为参与数。
  • 构造方法,CyclicBarrier(int parties,Runnable barrierAction):barrierAction,所有参与者都到达屏障时执行一次的命令。在一组线程中最后一个线程到达之后(但在释放所有线程之前),在该线程中执行改命令,该命令只在每个屏障点运行一次。若要在继续执行所有线程之前更新共享状态,此屏障操作很有用。
    • int await() throws InterruptedException,BrowkenBarrierException:线程执行过程会调用await()方法,表明自己已经到达屏障,该线程自己阻塞,等待其它线程也到达屏障;当所有线程都到达屏障,也即线程等待数等于参与数,则释放所有线程,让它们继续执行。返回值int表示到达当前线程的索引号,注意索引号是从parties-1开始减为0。BrokenBarrierException,屏障被破坏异常,当调用await时,或等待过程中屏障被破坏,则会抛出BrokenBarrierException
    • int await(long timeout,TimeUnit unit) throws InterruptedException,BrokenBarrierException,TimeoutException:等待指定时长,如到了时间还不能释放,则将抛出TimeoutException
    • int getNumberWaiting(): 获取当前在屏障处的线程数
    • boolean isBroken(): 判断屏障是否被破坏
    • void reset():重置屏障为初始化状态。如果当前有线程正在等待,则这些线程将被释放并抛出BrokenBarrierException

3、CyclicBarrier使用注意事项

  • 一定要确保有足够多的参与者线程,否则会一直阻塞在屏障处。
  • 在线程池中使用要注意,确保线程池的线程数大于等于参与数。

4、CyclicBarrier适用场景

  • 线程等待一起执行
  • 多次等待一起执行

5、CountDownLatch和CyclicBarrier对比

  • CountDownLatch是一部分线程等待另外一部分线程来唤醒
  • CyclicBarrier是参与线程彼此等待,都到达了,再一起执行
  • CountDownLatch不可以循环引用,CyclicBarrier可以循环使用

6、CyclicBarrier例子

  • 场景:多阶段等待一起出发

案例:公司组织周末旅游活动,大家各自从家出发到公司集合,大家都到了之后,出发到公司各自游玩,然后在公园门口集合,再去餐厅就餐,大家都到了就开始用餐。使用并非编程模拟场景。

参与者不变,多次彼此等待。正好可用CyclicBarrier的循环使用特性

代码语言:javascript
复制
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierExample {

    public static void main(String[] args) {
        int concurrency = 100;
        final CyclicBarrier cyclicBarrier = new CyclicBarrier(concurrency , ()->{
            System.out.println("*****************准备完成!************");
        });
        final Random random = new Random();
        for (int i = 0 ; i < concurrency; i++) {
            new Thread(() -> {
                try {
                    Thread.sleep(random.nextInt(10_000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println(Thread.currentThread().getName() + "准备就绪");
                try {
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
                System.out.println(
                        Thread.currentThread().getName() + " 开始工作....");
            }).start();
        }
    }
}

控制台打印:

代码语言:javascript
复制
... 
Thread-12准备就绪
Thread-58准备就绪
Thread-75准备就绪
Thread-25准备就绪
*****************准备完成!************
Thread-25 开始工作....
Thread-89 开始工作....
Thread-34 开始工作....
...
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-11-29 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、CyclicBarrier循环屏障定义
  • 2、CyclicBarrier用法以及原理
  • 3、CyclicBarrier使用注意事项
  • 4、CyclicBarrier适用场景
  • 5、CountDownLatch和CyclicBarrier对比
  • 6、CyclicBarrier例子
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档