Java多线程之同步工具类CyclicBarrier

Java多线程之同步工具类CyclicBarrier

什么是CyclicBarrier

CyclicBarrier是java.util.concurrent包下的一个同步工具类。它能够使线程等待至指定数量的线程都达到某个状态后再一起执行。

CyclicBarrier就像一个障碍物,当每个线程到达这个障碍物时,就必须停下来等待其他线程也到达障碍物,当所有线程都到达后,障碍物才会打开,让所有线程继续执行下去。

CyclicBarrier的构造方法

CyclicBarrier有多个构造方法,其中最常用的一个有两个参数:

public CyclicBarrier(int parties, Runnable barrierAction) { ... }
  • parties: 表示参与线程的数量
  • barrierAction: 当线程到达障碍物时,优先执行这个线程任务,可以为null

如果不传入barrierAction参数,线程到达障碍物后就直接继续执行。

CyclicBarrier的使用

使用CyclicBarrier主要分为两个步骤:初始化和等待。

初始化CyclicBarrier

在使用CyclicBarrier时,我们需要先初始化一个CyclicBarrier对象。以下是初始化CyclicBarrier的示例:

int count = 3;
CyclicBarrier cyclicBarrier = new CyclicBarrier(count);

以上代码创建了一个CyclicBarrier实例,该实例要求所有线程都到达3个障碍物,才能继续往下执行。

等待线程到达CyclicBarrier

在初始化完成后,所有线程都需要等待其他线程到达CyclicBarrier,当所有线程都到达时,CyclicBarrier将被打开,所有线程都可以继续往下执行。

Thread threadA = new Thread(() -> {
    System.out.println("Thread A is waiting at the barrier.");
    try {
        cyclicBarrier.await();
    } catch (InterruptedException | BrokenBarrierException e) {
        e.printStackTrace();
    }
    System.out.println("Thread A has passed the barrier.");
});

Thread threadB = new Thread(() -> {
    System.out.println("Thread B is waiting at the barrier.");
    try {
        cyclicBarrier.await();
    } catch (InterruptedException | BrokenBarrierException e) {
        e.printStackTrace();
    }
    System.out.println("Thread B has passed the barrier.");
});

Thread threadC = new Thread(() -> {
    System.out.println("Thread C is waiting at the barrier.");
    try {
        cyclicBarrier.await();
    } catch (InterruptedException | BrokenBarrierException e) {
        e.printStackTrace();
    }
    System.out.println("Thread C has passed the barrier.");
});

threadA.start();
threadB.start();
threadC.start();

以上代码创建了3个线程,并同时将它们启动,CyclicBarrier将阻塞所有线程,直到所有线程都到达障碍物。当所有线程都到达障碍物后,CyclicBarrier将打开,所有线程都可以继续执行下面的代码。

示例说明

示例1:多线程计算数组和

让多个线程同时计算一个大数组的和,最后将所有结果相加。

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

public class CalculateArraySumDemo {

    private static final int THREAD_COUNT = 5;  // 线程数
    private static final int ARRAY_LENGTH = 100; // 数组长度

    public static void main(String[] args) {
        int[] array = new int[ARRAY_LENGTH];
        for (int i = 0; i < ARRAY_LENGTH; i++) {
            array[i] = i + 1; // 初始化数组
        }

        CyclicBarrier cyclicBarrier = new CyclicBarrier(THREAD_COUNT, () -> {
            int sum = 0;
            for (int i = 0; i < THREAD_COUNT; i++) {
                sum += result[i]; // 将每个线程的结果相加
            }
            System.out.println("Array sum: " + sum);
        });

        ExecutorService executor = Executors.newCachedThreadPool();
        for (int i = 0; i < THREAD_COUNT; i++) {
            executor.execute(new CalculateTask(array, cyclicBarrier));
        }

        executor.shutdown();
    }

    static int[] result = new int[THREAD_COUNT];

    static class CalculateTask implements Runnable {
        private final int[] array;
        private final CyclicBarrier cyclicBarrier;

        public CalculateTask(int[] array, CyclicBarrier cyclicBarrier) {
            this.array = array;
            this.cyclicBarrier = cyclicBarrier;
        }

        @Override
        public void run() {
            int startIndex = result.length * (int) Thread.currentThread().getId();
            int endIndex = startIndex + result.length;
            for (int i = startIndex; i < endIndex; i++) {
                result[(int) Thread.currentThread().getId()] += array[i];
            }

            // 等待所有计算子任务完成
            try {
                cyclicBarrier.await();
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }
}

以上代码中,我们使用一个CyclicBarrier来实现线程间的同步。当每个线程计算完它们要求计算的数据后,会调用cyclicBarrier.await()方法,表示当前线程已经完成了它的任务,并且要等待其他线程也完成任务。

当所有子线程都计算完后,CyclicBarrier将触发barrierAction回调,在其回调中,将所有线程的计算结果相加,得到数组和,并打印到控制台上。

示例2:模拟赛跑

模拟N个选手比赛,最后公布排名。

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

public class RaceDemo {

    private static final int THREAD_COUNT = 5; // 选手数量
    private static final int ROUND_COUNT = 3;  // 跑三圈

    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(THREAD_COUNT);

        for (int i = 0; i < THREAD_COUNT; i++) {
            new Thread(new Player(cyclicBarrier)).start();
        }
    }

    static class Player implements Runnable {
        private final CyclicBarrier cyclicBarrier;

        public Player(CyclicBarrier cyclicBarrier) {
            this.cyclicBarrier = cyclicBarrier;
        }

        @Override
        public void run() {
            int round = 0;
            while (round < ROUND_COUNT) {
                try {
                    System.out.println("Player " + Thread.currentThread().getId() + " has run " + (round + 1) + " round.");
                    Thread.sleep((long) (Math.random() * 5000)); // 跑步随机时间

                    cyclicBarrier.await(); // 到达终点,开始等待

                    round++;
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }

            System.out.println("Player " + Thread.currentThread().getId() + " has arrived at the finish line.");
        }
    }
}

以上代码中,我们创建了5个Player线程模拟赛跑,这些线程共享一个CyclicBarrier对象。当一名选手到达终点,他将调用CyclicBarrierawait()方法,表明自己已经到达终点,并等待其他选手也到达终点,当所有选手都到达终点后,CyclicBarrier将调用CyclicBarrier的barrierAction回调,公布比赛排名。

总结

CyclicBarrier是一种多线程同步工具,它可以使一组线程到达某个同步点后,等待所有线程都到达同步点后再一起继续执行。我们可以通过CyclicBarrier来编写高效的并发程序,利用多核计算机的计算能力来提高程序的性能和吞吐量。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java多线程之同步工具类CyclicBarrier - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • 关于php 高并发解决的一点思路

    下面是关于PHP高并发解决的一点思路的完整攻略。 一、需求分析 在解决高并发问题之前,我们需要对需求进行分析,具体包括哪些方面: 1.1 并发量 需要先确定项目的具体并发量,这是解决高并发问题的基础。一般可以通过压力测试工具进行测试,将得出的结果作为后续优化的参考。 1.2 瓶颈分析 在确定并发量之后,需要对瓶颈进行分析,主要包括哪些方面: 数据库:主要是分…

    多线程 2023年5月16日
    00
  • 并发编程之Java内存模型volatile的内存语义

    让我来详细讲解一下Java内存模型volatile的内存语义。 什么是Java内存模型? Java内存模型指定了Java程序中多个线程之间的内存交互方式。Java内存模型决定了一个线程在什么时候能看到另一个线程对共享变量的写操作,以及如何同步访问共享变量。 什么是volatile变量? 在Java中,如果一个变量被声明为volatile类型,那么在多线程环境…

    多线程 2023年5月17日
    00
  • Python并发:多线程与多进程的详解

    Python并发:多线程与多进程的详解 一、概述 在Python中进行并发编程可以使用多线程和多进程,两者都可以利用多核CPU提高程序的性能。多线程主要用于IO密集型任务,多进程则适用于CPU密集型任务。 二、多线程 1. 创建线程 在Python中创建线程可以使用threading库,具体步骤如下: import threading def func():…

    多线程 2023年5月16日
    00
  • php多线程实现方法及用法实例详解

    PHP多线程实现方法及用法实例详解 什么是多线程? 多线程是指一个进程中包含多个执行路径,每个执行路径又称为线程。多线程程序具有多个并发执行的控制流,能提高程序的并行度,从而提高程序的运行效率。 为什么要使用多线程? 使用多线程可以提高程序的并行度,从而提高程序的运行效率。同时,多线程还可以让程序在执行IO等耗时操作时,不会被这些操作所阻塞,提高程序的响应速…

    多线程 2023年5月17日
    00
  • 详解JUC并发编程中的进程与线程学习

    详解JUC并发编程中的进程与线程学习攻略 一、进程与线程的概念及区别 进程:是指正在执行的程序的实例。每个进程都有独立的内存空间,它可以包括多个线程。 线程:是指程序中独立、并发执行的最小单位,它直接依赖于进程,一个进程可以创建多个线程。 进程与线程的最大区别在于进程是资源分配的最小单位,线程是CPU调度的最小单位。线程共享进程的内存空间以及其他系统资源。 …

    多线程 2023年5月16日
    00
  • JAVA如何解决并发问题

    为了解决并发问题,Java提供了以下解决方法: 同步方法(Synchronized Methods) 同步方法可以解决多线程访问共享数据时的并发问题。同步方法在方法签名中使用synchronized关键字来标记,使得该方法在同一时间只能被一个线程执行。当一个线程执行同步方法时,其他线程无法访问该方法,直到该线程完成对共享数据的操作并退出该方法。 示例1: p…

    多线程 2023年5月16日
    00
  • Java并发框架:Executor API详解

    Java并发框架:Executor API详解 Executor框架简介 Java的Executor框架是Java5中引入的,用于简化多线程编程模型。在Java5之前,Java多线程编程必须自己写很多代码来管理线程。但是,在Java5中,Executor框架可以处理所有线程管理的细节,让编程人员更加专注于业务逻辑,提高效率。 Executor框架的组成 Ex…

    多线程 2023年5月17日
    00
  • hadoop map-reduce中的文件并发操作

    关于”Hadoop Map-Reduce 中的文件并发操作”,我会给您提供以下完整攻略: 1. 背景知识 在 Hadoop 的 Map-Reduce 程序中,文件是作为输入和输出的主要载体。而在实际的应用场景中,由于对大数据处理的需求,经常会存在多个任务同时对同一文件进行读/写操作的情况,这时候不可避免地会出现文件的并发访问问题。为了避免出现因为并发访问而导…

    多线程 2023年5月16日
    00
合作推广
合作推广
分享本页
返回顶部