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来编写高效的并发程序,利用多核计算机的计算能力来提高程序的性能和吞吐量。

阅读剩余 77%

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

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

相关文章

  • php curl批处理实现可控并发异步操作示例

    下面是“php curl批处理实现可控并发异步操作示例”的完整攻略。 1. 准备工作 在开始之前,需要确保系统已经安装了curl扩展。可以通过以下命令来检查: php -m | grep curl 如果输出了curl,说明扩展已经安装成功。 2. 单个请求示例 首先来看一个简单的单个请求示例。代码如下: // 初始化curl $ch = curl_init(…

    多线程 2023年5月16日
    00
  • springboot内置的tomcat支持最大的并发量问题

    当使用Spring Boot时,自带Tomcat作为默认的Web服务器,但Tomcat的并发限制可能会在某些情况下成为瓶颈。在这里,我们将讲解如何配置Tomcat以支持更大的并发量。 1. 增加Tomcat的线程数 默认情况下,Spring Boot内置的Tomcat服务器使用200个线程作为最大并发数。如果需要更多的并发请求可以使用以下方式增加Tomcat…

    多线程 2023年5月17日
    00
  • 使用.Net实现多线程经验总结

    使用.Net实现多线程是提高程序并发处理能力的一种常用手段。下面将分享我的实战经验总结,并提供两个示例说明。 前置知识 在开始学习.Net多线程前,建议对以下知识有一定的掌握:- C#编程语言- 简单的数据结构和算法- 操作系统原理中进程和线程的概念 多线程设计原则 在多线程编程中,要遵循以下原则,保证程序的正确性和高效性: 避免竞态条件。 多个线程并发执行…

    多线程 2023年5月17日
    00
  • Java 常见的并发问题处理方法总结

    Java 并发编程是 Java 开发中的一个非常重要的领域,也是很多开发者关注的热点问题。在 Java 并发编程过程中,会出现各种各样的并发问题,如线程安全、死锁、竞态条件等。 针对这些并发问题,我们需要采用一些特定的解决方法和技术。接下来,我将介绍一些 Java 常见的并发问题处理方法总结。 Java 常见的并发问题 Java 常见的并发问题有以下几类: …

    多线程 2023年5月16日
    00
  • Java 多线程并发编程提高数据处理效率的详细过程

    Java 多线程并发编程是提高数据处理效率的重要手段。以下是详细的攻略: 什么是多线程并发编程 多线程并发编程指一个程序同时启动多个线程,每个线程执行不同的任务。在多线程并发编程中,线程同步和锁机制非常重要。线程同步是多个线程保证数据同步和互斥访问的机制,锁机制用于控制对共享资源的访问。 多线程并发编程的好处 多线程并发编程可以大大提高数据处理效率,特别是在…

    多线程 2023年5月16日
    00
  • Java并发编程示例(五):线程休眠与恢复

    Java并发编程示例(五):线程休眠与恢复是介绍Java多线程中线程休眠和恢复的教程。以下是完整攻略。 线程休眠与恢复 在Java多线程中,线程的休眠和恢复是两个比较重要的概念。休眠是暂停线程的执行,一定时间后再恢复执行;而恢复就是让线程继续执行。 Java提供了Thread.sleep()方法来实现线程的休眠,其中参数单位是毫秒。当线程处于休眠状态时,它不…

    多线程 2023年5月17日
    00
  • 详解Java多线程处理List数据

    接下来我将为您详细讲解“详解Java多线程处理List数据”的完整攻略。 引言 Java程序开发中,多线程处理List数据是非常常见的需求,尤其是在大数据量的情况下。本文将介绍如何使用Java多线程处理List数据。 使用Java多线程处理List数据的步骤 使用Java多线程处理List数据的步骤如下: 确定需要处理的List数据。 将List数据拆分成多…

    多线程 2023年5月17日
    00
  • Java并发 结合源码分析AQS原理

    Java并发 结合源码分析AQS原理 简介 Java中,AQS(AbstractQueuedSynchronizer)是一个并发同步框架,常被用于实现同步器、锁和其他一些并发工具。AQS本身提供了一些实现同步器的方法,同步器可以使用这些方法来构建不同的同步机制。 AQS的核心思想是维护一个FIFO的同步队列,通过加锁、解锁等同步操作,将线程放入队列中,并在条…

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