当前位置: 首页 > news >正文

CountDownLatch与CyclicBarrier使用及区别

CountDownLatch与CyclicBarrier使用及区别

  • 一、`CountDownLatch`
    • **主要用途**
    • **核心方法**
    • **使用示例**
      • 示例 1:主线程等待多个子线程完成任务
      • 示例 2:多个子线程等待主线程发出信号
    • **注意事项**
  • 二、`CyclicBarrier`
    • **主要用途**
    • **核心方法**
    • **使用示例**
      • 示例 1:多个线程相互等待
      • 示例 2:分阶段任务
    • **注意事项**
    • **`CyclicBarrier`与 `CountDownLatch` 的区别**
    • **适用场景**

一、CountDownLatch

java.util.concurrent.CountDownLatch 是 Java 并发编程中的一个同步工具类,用于让一个或多个线程等待其他线程完成操作后再继续执行。它的核心思想是通过一个计数器来实现线程的等待和唤醒。


主要用途

CountDownLatch 通常用于以下场景:

  1. 主线程等待多个子线程完成任务
    • 例如,主线程需要等待多个子线程初始化完成后才能继续执行。
  2. 多个子线程等待主线程发出信号
    • 例如,多个子线程需要等待主线程发出“开始”信号后才能同时执行。

核心方法

  1. CountDownLatch(int count)
    • 构造函数,初始化计数器。count 是需要等待的操作次数。
  2. void await()
    • 使当前线程等待,直到计数器减到 0。
  3. boolean await(long timeout, TimeUnit unit)
    • 使当前线程等待,直到计数器减到 0 或超时。
  4. void countDown()
    • 将计数器减 1,表示一个操作已完成。
  5. long getCount()
    • 返回当前计数器的值。

使用示例

示例 1:主线程等待多个子线程完成任务

import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {
    public static void main(String[] args) throws InterruptedException {
        int threadCount = 5;
        CountDownLatch latch = new CountDownLatch(threadCount);

        for (int i = 0; i < threadCount; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + " 完成任务");
                latch.countDown(); // 计数器减 1
            }).start();
        }

        latch.await(); // 主线程等待所有子线程完成任务
        System.out.println("所有任务已完成,主线程继续执行");
    }
}

输出:

Thread-0 完成任务
Thread-1 完成任务
Thread-2 完成任务
Thread-3 完成任务
Thread-4 完成任务
所有任务已完成,主线程继续执行

示例 2:多个子线程等待主线程发出信号

import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample2 {
    public static void main(String[] args) throws InterruptedException {
        int threadCount = 5;
        CountDownLatch startSignal = new CountDownLatch(1);

        for (int i = 0; i < threadCount; i++) {
            new Thread(() -> {
                try {
                    startSignal.await(); // 子线程等待主线程的信号
                    System.out.println(Thread.currentThread().getName() + " 开始执行");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }

        Thread.sleep(2000); // 模拟主线程准备时间
        System.out.println("主线程发出开始信号");
        startSignal.countDown(); // 主线程发出信号
    }
}

输出:

主线程发出开始信号
Thread-0 开始执行
Thread-1 开始执行
Thread-2 开始执行
Thread-3 开始执行
Thread-4 开始执行

注意事项

  1. 计数器不可重置
    • CountDownLatch 的计数器只能减不能增,一旦计数器减到 0,就不能再使用了。如果需要重复使用,可以考虑 CyclicBarrier
  2. 避免死锁
    • 确保所有线程都会调用 countDown(),否则主线程会一直等待。
  3. 性能开销
    • CountDownLatch 是基于 AQS(AbstractQueuedSynchronizer)实现的,性能较高,适合高并发场景。

二、CyclicBarrier

java.util.concurrent.CyclicBarrier 是 Java 并发编程中的一个同步工具类,用于让一组线程相互等待,直到所有线程都到达某个屏障点(Barrier Point)后再继续执行。与 CountDownLatch 不同,CyclicBarrier 是可以重复使用的。


主要用途

CyclicBarrier 通常用于以下场景:

  1. 多线程任务分阶段执行
    • 例如,多个线程需要先完成第一阶段的任务,然后同时开始第二阶段的任务。
  2. 并行计算
    • 例如,将一个大型计算任务拆分为多个子任务,每个子任务由一个线程处理,所有线程完成后合并结果。

核心方法

  1. CyclicBarrier(int parties)
    • 构造函数,初始化屏障,parties 是需要等待的线程数。
  2. CyclicBarrier(int parties, Runnable barrierAction)
    • 构造函数,初始化屏障,并指定所有线程到达屏障后执行的操作(barrierAction)。
  3. int await()
    • 使当前线程等待,直到所有线程都到达屏障。
  4. int await(long timeout, TimeUnit unit)
    • 使当前线程等待,直到所有线程都到达屏障或超时。
  5. void reset()
    • 重置屏障,使其可以重复使用。

使用示例

示例 1:多个线程相互等待

import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierExample {
    public static void main(String[] args) {
        int threadCount = 3;
        CyclicBarrier barrier = new CyclicBarrier(threadCount, () -> {
            System.out.println("所有线程已到达屏障,继续执行");
        });

        for (int i = 0; i < threadCount; i++) {
            new Thread(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + " 到达屏障");
                    barrier.await(); // 等待其他线程
                    System.out.println(Thread.currentThread().getName() + " 继续执行");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

输出:

Thread-0 到达屏障
Thread-1 到达屏障
Thread-2 到达屏障
所有线程已到达屏障,继续执行
Thread-2 继续执行
Thread-0 继续执行
Thread-1 继续执行

示例 2:分阶段任务

import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierExample2 {
    public static void main(String[] args) {
        int threadCount = 3;
        CyclicBarrier barrier = new CyclicBarrier(threadCount, () -> {
            System.out.println("当前阶段完成,进入下一阶段");
        });

        for (int i = 0; i < threadCount; i++) {
            new Thread(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + " 完成阶段 1");
                    barrier.await(); // 等待其他线程完成阶段 1

                    System.out.println(Thread.currentThread().getName() + " 完成阶段 2");
                    barrier.await(); // 等待其他线程完成阶段 2

                    System.out.println(Thread.currentThread().getName() + " 完成阶段 3");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

输出:

Thread-0 完成阶段 1
Thread-1 完成阶段 1
Thread-2 完成阶段 1
当前阶段完成,进入下一阶段
Thread-2 完成阶段 2
Thread-0 完成阶段 2
Thread-1 完成阶段 2
当前阶段完成,进入下一阶段
Thread-1 完成阶段 3
Thread-0 完成阶段 3
Thread-2 完成阶段 3

注意事项

  1. 屏障点操作
    • 如果指定了 barrierAction,它会在最后一个线程到达屏障后执行,然后所有线程才会继续执行。
  2. 异常处理
    • 如果某个线程在等待时被中断或超时,屏障会被破坏,所有等待的线程会抛出 BrokenBarrierException
  3. 重复使用
    • CyclicBarrier 可以重复使用,每次所有线程到达屏障后,计数器会自动重置。

CyclicBarrierCountDownLatch 的区别

特性CyclicBarrierCountDownLatch
计数器重置可重置不可重置
用途多个线程相互等待一个线程等待多个线程完成
触发条件所有线程到达屏障点计数器减到 0
重复使用支持不支持

适用场景

  • 如果任务需要分阶段执行,并且每个阶段需要所有线程同步,使用 CyclicBarrier
  • 如果只需要一个线程等待其他线程完成,使用 CountDownLatch

相关文章:

  • Visual Studio Code集成MarsCode AI
  • 【Python 初级函数详解】—— 参数沙漠与作用域丛林的求生指南
  • 693. 交替位二进制数
  • ETL-kettle数据转换使用详解
  • 利用STM32TIM自制延迟函数实验
  • jeecgboot项目idea启动项目(二)
  • Java基础语法38(异常处理try-catch和throws)
  • 40岁开始学Java:避免创建不必要的对象
  • 分治算法+题目
  • 基金 word-->pdf图片模糊的解决方法
  • MyBatis调用外部静态方法
  • 飞致云开源社区月度动态报告(2025年2月)
  • 基于HTML的贪吃蛇小游戏
  • 目前主流 AI 大模型体系全解析:架构、特点与应用
  • 代码规范和简化标准
  • macos下myslq图形化工具之Sequel Ace
  • 记Android12上一个原生bug引起的system_server crash
  • Scala的match表达式的基本简单介绍
  • ​Java 实体类中的常见问题:@Data 注解与 is 前缀字段的陷阱​
  • DrissionPage动态库过(某网)滑块(100%成功)
  • 江门关键词优化排名/seo优化啥意思
  • 武汉网站建设哪家好/社群推广平台
  • 前端做的比较好的网站/长春seo网站排名
  • 宁波seo服务推广平台/山东网络优化公司排名
  • 互联网建设网站/网站建设的一般步骤
  • 网站编辑工具/关键字优化用什么系统