前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Java 中 CycliBarriar 和 CountdownLatch 有什么区别?

Java 中 CycliBarriar 和 CountdownLatch 有什么区别?

作者头像
用户1289394
发布2023-08-22 16:54:51
发布2023-08-22 16:54:51
16900
代码可运行
举报
文章被收录于专栏:Java学习网Java学习网
运行总次数:0
代码可运行

CyclicBarrier和CountDownLatch都是Java中常用的多线程同步工具,它们主要用来协调多个线程之间的行为,以便达到某种共同目标。虽然它们有一些相似之处,但在应用场景和使用方法上也存在着比较明显的区别。

1、CyclicBarrier

CyclicBarrier是一个可重用的屏障,它允许多个线程等待彼此,并在所有线程都准备就绪后再统一执行代码。每个线程的执行先调用await()方法,然后被阻塞直到所有线程都调用了该方法后才会往下执行。而且,CyclicBarrier还可以指定一个barrierAction,在所有线程到达屏障后自动执行。

以计算矩阵乘积为例,使用CyclicBarrier时可以将其中的计算过程分成若干个子任务,然后将子任务分配给不同线程来计算。当所有的线程都已经完成了自己的计算后,程序就可以进入下一个阶段,将子矩阵的结果合并起来得到整个矩阵的乘积。通过CyclicBarrier实现多线程计算矩阵乘积的示例代码如下:

代码语言:javascript
代码运行次数:0
运行
复制
public class CyclicBarrierDemo {
    private static final int N = 4;
    private static final int NR = N * N;
    private static float[] a = new float[NR];
    private static float[] b = new float[NR];
    private static float[] c = new float[NR];
    private static CyclicBarrier barrier;

    public static void main(String[] args) {
        for (int i = 0; i < NR; i++) {
            a[i] = (float) Math.random();
            b[i] = (float) Math.random();
        }
        barrier = new CyclicBarrier(N, () -> System.out.println("所有线程已完成计算,结果已合并!"));
        for (int i = 0; i < N; i++) {
            new ComputeThread(i).start();
        }
        System.out.println("主线程结束!");
    }

    private static class ComputeThread extends Thread {
        int id;

        ComputeThread(int id) {
            this.id = id;
        }

        @Override
        public void run() {
            int from = id * N;
            int to = from + N;
            for (int k = 0; k < N; k++) {
                for (int i = from; i < to; i++) {
                    float sum = 0;
                    for (int j = k * N; j < (k + 1) * N; j++) {
                        sum += a[i * N + j] * b[j * N + k];
                    }
                    c[i] = sum;
                }
                try {
                    System.out.println("线程" + id + "已完成第" + (k + 1) + "次计算!");
                    barrier.await(); // 等待其他线程
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

2、CountdownLatch

CountdownLatch是一种非常基本的同步工具,它只有一个计数器,该计数器初始化为一个正整数,并且线程通过调用countDown()方法来减少计数器的值,当计数器减少到0时,所有等待线程开始执行。与CyclicBarrier不同的是,CountdownLatch的计数器只能使用一次,一旦计数器变成了0,就不能复位,因此称为“倒计数”屏障。

以同时实现多个网络请求并发的场景为例,可以在每个网络请求完成后调用CountDownLatch的countDown()方法,直到计数器值降为0之前,其它所有线程都被阻塞,然后才能继续执行相应的操作。下面给出一个简单的示例代码:

代码语言:javascript
代码运行次数:0
运行
复制
public class CountDownLatchDemo {
    private static final int COUNT = 5;
    private static List<String> results = new ArrayList<>();
    private static ExecutorService executorService = Executors.newFixedThreadPool(COUNT);
    private static CountDownLatch countDownLatch = new CountDownLatch(COUNT);

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < COUNT; i++) {
            final int n = i + 1;
            executorService.submit(() -> {
                String result = doRequest(n);
                results.add(result);
                System.out.println("请求" + n + "成功!");
                countDownLatch.countDown();
            });
        }
        countDownLatch.await(); // 等待所有请求完成
        System.out.println("全部请求已完成,结果为:" + results);
        executorService.shutdown();
    }

    private static String doRequest(int n) {
        try {
            Thread.sleep((long) (Math.random() * 5000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "result" + n;
    }
}

可以看出,CountDownLatch在应用场景上比较单一,适合在某个任务被拆分为多个独立子任务时,等待所有子任务执行完成。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-07-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java学习网 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档