并发同步工具CyclicBarrier 的使用介绍

概念

CyclicBarrier 是 Java 中的另一个同步辅助类,它可以让一组线程互相等待,直到所有线程都达到一个屏障点后再继续执行。与 CountDownLatch 不同的是,CyclicBarrier 的计数器可以循环使用,当所有线程都到达屏障点后,计数器会重置,可以被复用。

所谓 Cyclic 即循环的意思,所谓 Barrier 即屏障的意思。所以综合起来,CyclicBarrier 指的就是循环屏障,虽然这个叫法很奇怪,但是却能很好地表达其含义。

CyclicBarrier 工具类允许一组线程相互等待,直到所有线程都到达一个公共的屏障点,然后这些线程一起继续执行后继逻辑。之所以称之为 “循环”,是因为在所有线程都释放了对这个屏障的使用后,这个屏障还可以重新使用。我们通过一张图可以直观了解其表达的控制模型。

 

CyclicBarrier 的主要方法包括:

  1. 构造方法:CyclicBarrier(int parties) 构造一个 CyclicBarrier 对象,指定参与线程的数量 parties。
  2. await():让当前线程等待,直到所有参与线程都到达屏障点。

CyclicBarrier 的典型用法包括:

  1. 多个线程分阶段执行任务,每个阶段结束后等待其他线程,然后一起执行下一个阶段。
  2. 多个线程同时执行不同任务,等待所有任务完成后再进行下一步操作。

基本用法

public class CyclicBarrierExample1 {

    private static final CyclicBarrier barrier = new CyclicBarrier(5);

    private static  CyclicBarrier barrier 2= new CyclicBarrier(5,new Runnable() {
        @Override
        public void run() {
            System.out.println("5人已来,可以开席了");
        }
    });

    public static void main(String[] args) throws Exception {

        ExecutorService executor = Executors.newCachedThreadPool();

        for (int i = 0; i < 10; i++) {
            final int threadNum = i;
            Thread.sleep(1000);
            executor.execute(() -> {
                try {
                    race(threadNum);
                } catch (Exception e) {
                    log.error("exception", e);
                }
            });
        }
        executor.shutdown();
    }

    private static void race(int threadNum) throws Exception {
        Thread.sleep(1000);
        log.info("{} is ready", threadNum);
        barrier.await();
        log.info("{} continue", threadNum);
    }

 

其他方法介绍

除过上面代码中使用的最基本的 await()方法之外,还有下面几个方法大家可以了解一下。

    1. CyclicBarrier(int parties)
      相比案例中使用的 CyclicBarrier(int parties, Runnable barrierAction) 构造方法,此方法只用于控制并发线程,不做屏障点到达后的其他动作。

    2. await(long timeout, TimeUnit unit) 方法
      此方法可以设置等待的时限,当时限过后还未被唤起,则直接自行唤醒继续执行后继任务。

 private static void race(int threadNum) throws Exception {
        Thread.sleep(1000);
        log.info("{} is ready", threadNum);
        try {
            barrier.await(2000, TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            log.warn("BarrierException", e);
        }
        log.info("{} continue", threadNum);
    }

 

getNumberWaiting() 方法

    1. 调用此方法,可以获得当前还在等待屏障点解除的线程数,一般用于了解整体处理进度。

 

posted @ 2024-04-11 17:50  黄橙  阅读(861)  评论(0)    收藏  举报