CountDownLatch和CyclicBarrier你使用过吗?

1 CountDownLatch

1.1 含义

一种同步辅助,允许一个或多个线程等待一组正在其他线程中执行的操作完成。CountDownLatch使用给定的计数进行初始化。由于对countDown方法的调用,await方法会阻塞,直到当前计数为零,在此之后,所有正在等待的线程都会被释放,后续对await的调用会立即返回。这是一种一次性现象——计数无法重置。如果需要重置计数的版本,可以考虑使用CyclicBarrier。
CountDownLatch是一个通用的同步工具,可以用于许多目的。初始化计数为1的CountDownLatch作为一个简单的打开/关闭锁:所有调用await的线程都在门上等待,直到它被调用countDown的线程打开。初始化为N的CountDownLatch可以用来让一个线程等待,直到N个线程完成某个动作,或者某个动作已经完成N次。
CountDownLatch的一个有用属性是,它不要求调用countDown的线程等待计数达到0后再继续,它只是阻止任何线程通过await,直到所有线程都可以通过。

1.2 使用场景举例

公司要选择一个办公室开董事会,董事会共有股东十个人,需要等每个股东都要到办公室才能开会,我们把每个股东视为一个线程,把开会这个事件视为主线程。
CountDownLatch和CyclicBarrier你使用过吗?

1.3 代码实现

/**
 * @desc: JUC CountDownLatch应用场景
 * @author: YanMingXin
 * @create: 2021/7/31-10:24
 **/
public class Test01 {
    public static void main(String[] args) throws InterruptedException {
        //公司开会需要集齐董事会10个人,10个人不分先后,只要来齐了才能开会
        CountDownLatch latch = new CountDownLatch(10);
        //十个人每个人一个线程
        for (int i = 0; i <= 10; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "到场");
                //增加一个人
                latch.countDown();
            }, String.valueOf(i)).start();
        }
        //主线程等待
        latch.await();
        System.out.println("开始开会......");
    }
}

测试结果

CountDownLatch和CyclicBarrier你使用过吗?

2 CyclicBarrier

2.1 含义

一种同步辅助,它允许一组线程都等待彼此到达一个共同的障碍点。CyclicBarrier在涉及固定大小的线程的程序中非常有用,这些线程偶尔必须相互等待。这个屏障被称为循环屏障,因为在等待的线程被释放后,它可以被重用。
CyclicBarrier支持一个可选的Runnable命令,该命令在每个barrier点运行一次,在该组的最后一个线程到达之后,但在任何线程被释放之前。这个barrier操作对于在任何一方继续之前更新共享状态非常有用。

2.2 使用场景举例

公司开完董事会后,为了保证安全性需要将办公室锁起来,当然锁门之前需要每个人都要走出来,我们仍旧把每个人当作一个线程,把锁门的事件当做主线程。

2.3 代码实现

/**
 * @desc: JUC CyclicBarrier
 * @author: YanMingXin
 * @create: 2021/7/31-10:31
 **/
public class Test02 {
    public static void main(String[] args) {
        //公司董事会开完会要等全部出去才能锁门
        CyclicBarrier barrier = new CyclicBarrier(10, () -> {
            System.out.println("办公室锁门......");
        });
        for (int i = 1; i <= 10; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName());
                try {
                    //等待锁门
                    barrier.await();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }, String.valueOf(i)).start();
        }
    }
}

测试结果:

CountDownLatch和CyclicBarrier你使用过吗?

3 结语

当然以上的使用场景是最常见的,以后有时间的话还要研究下CountDownLatch和CyclicBarrier的其他使用场景和原理,敬请期待哦!

上一篇:CountDownLatch


下一篇:CountDownLatch