Phaser、CountDownLatch 和 CyclicBarrier 区别对比

1. CountDownLatch - 等待所有子任务完成

特点:

一次性,不能重用。

适用于主线程等待所有子线程完成任务

子线程完成任务后调用 countDown() 递减计数,主线程 await() 等待计数变为 0 后继续执行。

示例:

import java.util.concurrent.CountDownLatch;

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

        for (int i = 0; i < taskCount; i++) {
            final int taskId = i;
            new Thread(() -> {
                System.out.println("任务 " + taskId + " 开始执行...");
                try {
                    Thread.sleep((long) (Math.random() * 2000)); // 模拟任务执行时间
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("任务 " + taskId + " 完成!");
                latch.countDown(); // 任务完成,计数器 -1
            }).start();
        }

        System.out.println("等待所有任务完成...");
        latch.await(); // 阻塞,直到 countDown 变为 0
        System.out.println("所有任务已完成,主线程继续执行!");
    }
}

输出示例:

任务 0 开始执行...
任务 1 开始执行...
任务 2 开始执行...
等待所有任务完成...
任务 1 完成!
任务 0 完成!
任务 2 完成!
所有任务已完成,主线程继续执行!

2. CyclicBarrier - 线程到达屏障后同步执行

特点:

可以重用,多个线程到达屏障后一起继续执行

所有线程都要 await(),才能一起继续

可指定 barrierAction 作为回调,在所有线程到达时执行额外任务。

示例:

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

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

        for (int i = 0; i < numThreads; i++) {
            final int threadId = i;
            new Thread(() -> {
                System.out.println("线程 " + threadId + " 准备执行任务...");
                try {
                    Thread.sleep((long) (Math.random() * 2000)); // 模拟任务执行
                    System.out.println("线程 " + threadId + " 到达屏障点,等待其他线程...");
                    barrier.await(); // 等待所有线程到达屏障
                    System.out.println("线程 " + threadId + " 继续执行!");
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }

输出示例:

线程 0 准备执行任务...
线程 1 准备执行任务...
线程 2 准备执行任务...
线程 2 到达屏障点,等待其他线程...
线程 0 到达屏障点,等待其他线程...
线程 1 到达屏障点,等待其他线程...
>>> 所有线程已到达屏障,执行 BarrierAction <<<
线程 1 继续执行!
线程 2 继续执行!
线程 0 继续执行!

3. Phaser - 多阶段同步

特点:

可重用,支持多阶段

支持动态增加或减少线程,比 CountDownLatchCyclicBarrier 更灵活。

每个阶段线程不同,arriveAndAwaitAdvance() 进入下一个阶段

示例:

import java.util.concurrent.Phaser;

public class PhaserExample {
    public static void main(String[] args) {
        Phaser phaser = new Phaser(1); // 注册主线程

        for (int i = 0; i < 3; i++) {
            phaser.register(); // 动态增加线程
            final int threadId = i;
            new Thread(() -> {
                System.out.println("线程 " + threadId + " 开始执行阶段 1...");
                phaser.arriveAndAwaitAdvance(); // 等待所有线程完成阶段 1

                System.out.println("线程 " + threadId + " 进入阶段 2...");
                phaser.arriveAndAwaitAdvance(); // 等待所有线程完成阶段 2

                System.out.println("线程 " + threadId + " 进入阶段 3...");
                phaser.arriveAndDeregister(); // 线程完成所有阶段,注销
            }).start();
        }

        while (!phaser.isTerminated()) {
            int phase = phaser.getPhase();
            System.out.println("主线程等待第 " + phase + " 阶段完成...");
            phaser.arriveAndAwaitAdvance(); // 控制主线程进入下一个阶段
        }

        System.out.println("所有阶段完成,主线程退出!");
    }
}

输出示例:

线程 0 开始执行阶段 1...
线程 1 开始执行阶段 1...
线程 2 开始执行阶段 1...
主线程等待第 0 阶段完成...
线程 0 进入阶段 2...
线程 1 进入阶段 2...
线程 2 进入阶段 2...
主线程等待第 1 阶段完成...
线程 0 进入阶段 3...
线程 1 进入阶段 3...
线程 2 进入阶段 3...
主线程等待第 2 阶段完成...
所有阶段完成,主线程退出!

4. 选择指南

需求推荐方案
让主线程等待所有子任务完成后再执行CountDownLatch
让一批线程同步后一起执行下一步CyclicBarrier
任务有多个阶段,每个阶段线程可能不同Phaser
任务不可重复,只执行一次CountDownLatch
任务需要循环多次执行CyclicBarrier
线程数动态变化Phaser
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值