浅谈CountDownLatch 和 CyclicBarrier

CountDownLatch

CountDownLatch,闭锁,是一个同步工具类,用来协调多个线程之间的同步。

CountDownLatch是Java并发编程中的一把利器,它的优点在于能够简洁高效地协调多个线程的执行顺序,确保一组线程都完成后才触发其他线程的执行,适用于资源加载、任务初始化等场景。它提供了清晰的等待/通知机制,易于理解和使用,是提升多线程程序性能和可靠性的重要工具,但同时,它也有一些局限性,比如无法重置计数,一旦计数到零,就不能再次使用了。而且,它只能等待固定数量的线程,不够灵活。

简单来说,当一个或者多个线程调用await方法时,会阻塞当前线程,并且CountDownLatch本身内置了一个方法计数器,其他线程调用 countDown 方法使计数器 - 1,当计数器的值变为0时,调用 await 方法被阻塞的线程会被唤醒,继续执行。

不使用CountDownLatch

因为线程是竞争执行的,如果不使用CountDownLatch的话, 无法保证主线程最后执行

    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "到达指定地点");
            }).start();
        }
        System.out.println(Thread.currentThread().getName() + "五个同学都到齐了!");
    }

在这里插入图片描述

使用CountDownLatch

可以看到,主线程最后才执行

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(5);
        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "到达指定地点");
                countDownLatch.countDown();
            }).start();
        }
            // 主线程在此等待,直到所有工作线程都完成任务  
        countDownLatch.await();
        System.out.println(Thread.currentThread().getName() + "五个同学都到齐了!");
    }

在这里插入图片描述

CyclicBarrier

CyclicBarrier,循环屏障,它支持一组线程相互等待,直到最后一个线程到达屏障点时,所有线程才会继续执行。CyclicBarrier可以被重用,即当所有等待的线程都被释放后,它可以再次被用来让另一组线程等待。

例子

宿舍五人一起去食堂干饭,要等大家都回来再出发,人齐后大家都开炫

public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(5, () -> {
            System.out.println("人齐了,集合去干饭!");
        });
        for (int i = 0; i < 5; i++) {
            int finalI = i;
            new Thread(() -> {
                System.out.println("老" + finalI + "到了集合地点");
                try {
                    cyclicBarrier.await();
                    System.out.println("老" + finalI + "开炫");
                } catch (InterruptedException | BrokenBarrierException e) {
                    throw new RuntimeException(e);
                }
            }).start();
        }
    }

执行结果如下
在这里插入图片描述

可以看到使用 CountDownLatch ,调用 countDown方法之后,之后的代码仍会继续执行,CountDownLatch 只能保证主线程或者调用await方法最后执行,其他调用countDown方法的线程早就执行结束了。

而 CyclicBarrier 的 await() 方法会阻塞,等所有线程执行结束后,所有调用 await() 线程会一起执行。

相同点

  1. 同步功能:
  • 两者都提供了等待多个线程完成特定任务的能力。
  • 它们都可以用来协调一组线程之间的执行顺序。
  1. 等待机制:
  • 在使用这两种工具时,某些线程会阻塞,直到满足某个条件(比如计数器达到零或所有线程到达屏障)。
  1. 线程等待:
  • 当线程调用await()方法时,它们都会进入等待状态,直到满足释放条件。
  1. 灵活性:
  • 它们都允许在等待期间执行某些操作,如中断等待的线程。
  1. 异常处理:
  • 如果在等待过程中发生异常,两个工具类都能通过异常传播机制来处理这些异常。

不同点

  1. CountDownLatch 是一次性的,CyclicBarrier 是可循环利用的
  2. CountDownLatch 的计数器只能使用一次,而CyclicBarrier 的计数器可以使用 reset方法重置
  3. CountDownLatch一般用于某个线程A等待若干个其他线程执行完任务之后,它才执行;而CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

每天吃八顿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值