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

x33g5p2x  于2021-11-29 转载在 其他  
字(2.2k)|赞(0)|评价(0)|浏览(613)

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的循环使用特性

  1. import java.util.Random;
  2. import java.util.concurrent.BrokenBarrierException;
  3. import java.util.concurrent.CyclicBarrier;
  4. public class CyclicBarrierExample {
  5. public static void main(String[] args) {
  6. int concurrency = 100;
  7. final CyclicBarrier cyclicBarrier = new CyclicBarrier(concurrency , ()->{
  8. System.out.println("*****************准备完成!************");
  9. });
  10. final Random random = new Random();
  11. for (int i = 0 ; i < concurrency; i++) {
  12. new Thread(() -> {
  13. try {
  14. Thread.sleep(random.nextInt(10_000));
  15. } catch (InterruptedException e) {
  16. e.printStackTrace();
  17. }
  18. System.out.println(Thread.currentThread().getName() + "准备就绪");
  19. try {
  20. cyclicBarrier.await();
  21. } catch (InterruptedException e) {
  22. e.printStackTrace();
  23. } catch (BrokenBarrierException e) {
  24. e.printStackTrace();
  25. }
  26. System.out.println(
  27. Thread.currentThread().getName() + " 开始工作....");
  28. }).start();
  29. }
  30. }
  31. }

控制台打印:

  1. ...
  2. Thread-12准备就绪
  3. Thread-58准备就绪
  4. Thread-75准备就绪
  5. Thread-25准备就绪
  6. *****************准备完成!************
  7. Thread-25 开始工作....
  8. Thread-89 开始工作....
  9. Thread-34 开始工作....
  10. ...

相关文章