并发编程系列之CyclicBarrier用法简介
Posted smileNicky
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并发编程系列之CyclicBarrier用法简介相关的知识,希望对你有一定的参考价值。
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的循环使用特性
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();
控制台打印:
...
Thread-12准备就绪
Thread-58准备就绪
Thread-75准备就绪
Thread-25准备就绪
*****************准备完成!************
Thread-25 开始工作....
Thread-89 开始工作....
Thread-34 开始工作....
...
以上是关于并发编程系列之CyclicBarrier用法简介的主要内容,如果未能解决你的问题,请参考以下文章