Java 中 CyclicBarrier 和 CountDownLatch 的区别

简介: 【8月更文挑战第22天】

概述

CyclicBarrierCountDownLatch 是 Java 中用于线程同步的两个并发工具。虽然这两个类都用于协调线程,但它们有不同的目的和用法。

CyclicBarrier

CyclicBarrier 是一个可重复使用的同步点,允许一组线程等待直到所有线程都到达该点。一旦所有线程都到达该点,屏障就会解除,所有线程都可以继续执行。

CountDownLatch

CountDownLatch 是一个一次性同步点,允许一个或多个线程等待直到一个计数器达到零。一旦计数器达到零,所有等待的线程都可以继续执行。

主要区别

  • 可重复使用性: CyclicBarrier 是可重复使用的,这意味着它可以在线程到达屏障后重置并再次使用。CountDownLatch 是不可重复使用的,一旦计数器达到零,它就完成了。
  • 等待条件: CyclicBarrier 等待所有线程到达屏障。CountDownLatch 等待计数器达到零。
  • 线程唤醒: CyclicBarrier 一次唤醒所有等待的线程。CountDownLatch 逐个唤醒等待的线程。

示例

以下示例演示了 CyclicBarrierCountDownLatch 之间的区别:

CyclicBarrier

public class CyclicBarrierExample {
   

    public static void main(String[] args) {
   
        // 创建一个具有 3 个参与者的 CyclicBarrier
        CyclicBarrier barrier = new CyclicBarrier(3);

        // 创建 3 个线程
        Thread t1 = new Thread(() -> {
   
            try {
   
                // 线程 1 到达屏障
                barrier.await();
                System.out.println("线程 1 已到达屏障。");
            } catch (Exception e) {
   
                e.printStackTrace();
            }
        });

        Thread t2 = new Thread(() -> {
   
            try {
   
                // 线程 2 到达屏障
                barrier.await();
                System.out.println("线程 2 已到达屏障。");
            } catch (Exception e) {
   
                e.printStackTrace();
            }
        });

        Thread t3 = new Thread(() -> {
   
            try {
   
                // 线程 3 到达屏障
                barrier.await();
                System.out.println("线程 3 已到达屏障。");
            } catch (Exception e) {
   
                e.printStackTrace();
            }
        });

        // 启动线程
        t1.start();
        t2.start();
        t3.start();
    }
}

输出:

线程 1 已到达屏障。
线程 2 已到达屏障。
线程 3 已到达屏障。

在这个示例中,三个线程都到达屏障后,屏障解除,所有线程继续执行。

CountDownLatch

public class CountDownLatchExample {
   

    public static void main(String[] args) {
   
        // 创建一个具有 3 个计数的 CountDownLatch
        CountDownLatch latch = new CountDownLatch(3);

        // 创建 3 个线程
        Thread t1 = new Thread(() -> {
   
            try {
   
                // 线程 1 完成任务
                latch.countDown();
                System.out.println("线程 1 已完成任务。");
            } catch (Exception e) {
   
                e.printStackTrace();
            }
        });

        Thread t2 = new Thread(() -> {
   
            try {
   
                // 线程 2 完成任务
                latch.countDown();
                System.out.println("线程 2 已完成任务。");
            } catch (Exception e) {
   
                e.printStackTrace();
            }
        });

        Thread t3 = new Thread(() -> {
   
            try {
   
                // 线程 3 完成任务
                latch.countDown();
                System.out.println("线程 3 已完成任务。");
            } catch (Exception e) {
   
                e.printStackTrace();
            }
        });

        // 启动线程
        t1.start();
        t2.start();
        t3.start();

        // 等待所有线程完成任务
        try {
   
            latch.await();
            System.out.println("所有线程已完成任务。");
        } catch (Exception e) {
   
            e.printStackTrace();
        }
    }
}

输出:

线程 1 已完成任务。
线程 2 已完成任务。
线程 3 已完成任务。
所有线程已完成任务。

在这个示例中,三个线程完成任务后,计数器达到零,所有等待的线程继续执行。

总结

CyclicBarrierCountDownLatch 都是有用的并发工具,用于协调线程。CyclicBarrier 用于同步一组线程,直到它们都到达一个点,而 CountDownLatch 用于同步一个或多个线程,直到一个计数器达到零。选择哪一个工具取决于任务的需要。

目录
相关文章
|
22天前
|
Java 程序员 调度
Java 高级面试技巧:yield() 与 sleep() 方法的使用场景和区别
本文详细解析了 Java 中 `Thread` 类的 `yield()` 和 `sleep()` 方法,解释了它们的作用、区别及为什么是静态方法。`yield()` 让当前线程释放 CPU 时间片,给其他同等优先级线程运行机会,但不保证暂停;`sleep()` 则让线程进入休眠状态,指定时间后继续执行。两者都是静态方法,因为它们影响线程调度机制而非单一线程行为。这些知识点在面试中常被提及,掌握它们有助于更好地应对多线程编程问题。
55 9
|
27天前
|
安全 Java 程序员
Java面试必问!run() 和 start() 方法到底有啥区别?
在多线程编程中,run和 start方法常常让开发者感到困惑。为什么调用 start 才能启动线程,而直接调用 run只是普通方法调用?这篇文章将通过一个简单的例子,详细解析这两者的区别,帮助你在面试中脱颖而出,理解多线程背后的机制和原理。
59 12
|
2月前
|
Java
Java社招面试题:& 和 && 的区别,HR的套路险些让我翻车!
今日分享的主题是如何区分&和&&的区别,提高自身面试的能力。主要分为以下四部分。 1、自我面试经历 2、&amp和&amp&amp的不同之处 3、&对&&的不同用回答逻辑解释 4、彩蛋
|
3月前
|
Java 程序员
Java社招面试题:& 和 && 的区别,HR的套路险些让我翻车!
小米,29岁程序员,分享了一次面试经历,详细解析了Java中&和&&的区别及应用场景,展示了扎实的基础知识和良好的应变能力,最终成功获得Offer。
107 14
|
3月前
|
Java
Java之CountDownLatch原理浅析
本文介绍了Java并发工具类`CountDownLatch`的使用方法、原理及其与`Thread.join()`的区别。`CountDownLatch`通过构造函数接收一个整数参数作为计数器,调用`countDown`方法减少计数,`await`方法会阻塞当前线程,直到计数为零。文章还详细解析了其内部机制,包括初始化、`countDown`和`await`方法的工作原理,并给出了一个游戏加载场景的示例代码。
Java之CountDownLatch原理浅析
|
2月前
|
Java
java中面向过程和面向对象区别?
java中面向过程和面向对象区别?
36 1
|
3月前
|
存储 缓存 安全
java 中操作字符串都有哪些类,它们之间有什么区别
Java中操作字符串的类主要有String、StringBuilder和StringBuffer。String是不可变的,每次操作都会生成新对象;StringBuilder和StringBuffer都是可变的,但StringBuilder是非线程安全的,而StringBuffer是线程安全的,因此性能略低。
104 8
|
2天前
|
Java 程序员 开发者
Java社招面试题:一个线程运行时发生异常会怎样?
大家好,我是小米。今天分享一个经典的 Java 面试题:线程运行时发生异常,程序会怎样处理?此问题考察 Java 线程和异常处理机制的理解。线程发生异常,默认会导致线程终止,但可以通过 try-catch 捕获并处理,避免影响其他线程。未捕获的异常可通过 Thread.UncaughtExceptionHandler 处理。线程池中的异常会被自动处理,不影响任务执行。希望这篇文章能帮助你深入理解 Java 线程异常处理机制,为面试做好准备。如果你觉得有帮助,欢迎收藏、转发!
33 14
|
5天前
|
安全 Java 程序员
Java 面试必问!线程构造方法和静态块的执行线程到底是谁?
大家好,我是小米。今天聊聊Java多线程面试题:线程类的构造方法和静态块是由哪个线程调用的?构造方法由创建线程实例的主线程调用,静态块在类加载时由主线程调用。理解这些细节有助于掌握Java多线程机制。下期再见! 简介: 本文通过一个常见的Java多线程面试题,详细讲解了线程类的构造方法和静态块是由哪个线程调用的。构造方法由创建线程实例的主线程调用,静态块在类加载时由主线程调用。理解这些细节对掌握Java多线程编程至关重要。
34 13
|
6天前
|
安全 Java 开发者
【JAVA】封装多线程原理
Java 中的多线程封装旨在简化使用、提高安全性和增强可维护性。通过抽象和隐藏底层细节,提供简洁接口。常见封装方式包括基于 Runnable 和 Callable 接口的任务封装,以及线程池的封装。Runnable 适用于无返回值任务,Callable 支持有返回值任务。线程池(如 ExecutorService)则用于管理和复用线程,减少性能开销。示例代码展示了如何实现这些封装,使多线程编程更加高效和安全。

热门文章

最新文章