Java并发编程之栅栏(CyclicBarrier)实例介绍

Java并发编程之栅栏(CyclicBarrier)实例介绍

什么是栅栏(CyclicBarrier)?

栅栏(CyclicBarrier)是Java并发编程中的一种工具类,它可以在多个线程中实现同步。当栅栏的计数器(CyclicBarrier(int parties)构造函数中的参数)被减到0时,所有由该栅栏等待的线程才能继续执行。

栅栏的使用方法

在使用栅栏之前,需要先创建一个栅栏。

CyclicBarrier barrier = new CyclicBarrier(int parties);

参数parties是栅栏需要等待的线程数量。

然后在多个线程中调用栅栏的await方法。

try {
    barrier.await();
} catch (InterruptedException ex) {
    // handle exception
} catch (BrokenBarrierException ex) {
    // handle exception
}

当线程调用await方法时,它会被阻塞,直到所有栅栏等待的线程(即parties数量)都调用了await方法。然后所有等待的线程都会被同时唤醒,并继续执行。

栅栏示例说明一

在下面的示例中,我们创建了3个线程(即parties的数量为3),每个线程都会打印出一个数字。等到所有线程都打印完数字后,再打印一条语句。

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

public class BarrierExample1 {
    public static void main(String[] args) {
        int parties = 3;

        CyclicBarrier barrier = new CyclicBarrier(parties, new Runnable() {
            @Override
            public void run() {
                System.out.println("All threads have finished printing!");
            }
        });

        for (int i = 0; i < parties; i++) {
            new Thread(new PrintNumberTask(i, barrier)).start();
        }
    }

    static class PrintNumberTask implements Runnable {
        private int number;
        private CyclicBarrier barrier;

        public PrintNumberTask(int number, CyclicBarrier barrier) {
            this.number = number;
            this.barrier = barrier;
        }

        @Override
        public void run() {
            try {
                // 打印数字
                System.out.println("Thread " + number + " prints " + number);
                // 等待其他线程打印数字
                barrier.await();
            } catch (InterruptedException ex) {
                // handle exception
            } catch (BrokenBarrierException ex) {
                // handle exception
            }
        }
    }
}

运行结果:

Thread 0 prints 0
Thread 2 prints 2
Thread 1 prints 1
All threads have finished printing!

可以看到,三个线程的打印顺序不一定是按照线程号顺序的,但是最终都会在所有线程都打印完数字后,打印出一条语句。

栅栏示例说明二

下面我们再来看一个更实际的例子。假设我们有一个大文件需要处理,我们可以把这个文件分割成多个小文件,每个线程处理一个小文件,处理完毕后再把结果合并起来。使用栅栏可以很方便地实现这个过程。

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class BarrierExample2 {
    public static void main(String[] args) {
        int nThreads = 3;
        String filename = "big_file.txt";

        // 将文件分割为n个子文件
        List<File> files = splitFile(new File(filename), nThreads);

        CyclicBarrier barrier = new CyclicBarrier(nThreads, new Runnable() {
            @Override
            public void run() {
                System.out.println("All threads have finished processing files!");
            }
        });

        List<Thread> threads = new ArrayList<>();

        for (int i = 0; i < nThreads; i++) {
            File file = files.get(i);
            Thread thread = new Thread(new FileProcessingTask(file, barrier));
            threads.add(thread);
            thread.start();
        }

        for (Thread thread : threads) {
            try {
                thread.join();
            } catch (InterruptedException ex) {
                // handle exception
            }
        }

        // 合并处理结果
        // mergeResult(files);
    }

    static List<File> splitFile(File file, int n) {
        List<File> files = new ArrayList<>();

        // calculate the size of each chunk
        long chunkSize = file.length() / n;

        try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
            String line;
            long bytesRead = 0;
            int fileNumber = 0;
            File outputFile = new File(file.getParent(), file.getName() + "." + fileNumber);
            files.add(outputFile);
            while ((line = reader.readLine()) != null) {
                if (bytesRead + line.getBytes().length > chunkSize) {
                    // start a new file
                    outputFile = new File(file.getParent(), file.getName() + "." + (++fileNumber));
                    files.add(outputFile);
                    bytesRead = 0;
                }
                // write the line to the current file
                // ...

                bytesRead += line.getBytes().length;
            }
        } catch (IOException ex) {
            // handle exception
        }

        return files;
    }

    static void mergeResult(List<File> files) {
        // merge the files
        // ...
    }

    static class FileProcessingTask implements Runnable {
        private File file;
        private CyclicBarrier barrier;

        public FileProcessingTask(File file, CyclicBarrier barrier) {
            this.file = file;
            this.barrier = barrier;
        }

        @Override
        public void run() {
            // process the file
            // ...

            try {
                // 等待其他线程处理完毕
                barrier.await();
            } catch (InterruptedException ex) {
                // handle exception
            } catch (BrokenBarrierException ex) {
                // handle exception
            }
        }
    }
}

在上面的代码中,我们先将大文件big_file.txt分割成3个小文件,然后创建了3个线程,每个线程负责处理一个小文件。当每个线程处理完毕后,都会调用栅栏的await方法,等待其他线程也处理完毕。当所有线程都处理完毕后,栅栏的Runnable会被调用。

这里的示例还省略了文件处理和合并的具体代码,读者可以自行实现。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java并发编程之栅栏(CyclicBarrier)实例介绍 - Python技术站

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

相关文章

  • 深入解析Java并发程序中线程的同步与线程锁的使用

    深入解析Java并发程序中线程的同步与线程锁的使用 在Java并发程序中,线程的同步和线程锁是必不可少的。线程的同步是指多个线程协同工作,按一定的顺序执行,而线程锁则是保证多个线程访问共享资源时数据的正确性和一致性。 线程同步 Java中线程同步的主要方式有以下两种: 1. synchronized关键字 synchronized关键字可以修饰方法和代码块,…

    多线程 2023年5月16日
    00
  • java多线程中执行多个程序的实例分析

    Java中的多线程机制是计算机科学中的重要部分,它允许一个程序同时执行多个任务,以实现并发性和并行性的目标。这篇攻略将向你介绍Java中如何实现多线程执行多个程序实例的方法。 1. 创建多个线程 在Java中,要实现多线程执行多个程序实例的目标,我们需要首先创建多个线程。这可以通过定义一个继承自Thread类的自定义类来实现。以下是一个简单的示例: clas…

    多线程 2023年5月17日
    00
  • Java 并发编程之ThreadLocal详解及实例

    Java 并发编程之ThreadLocal详解及实例攻略 什么是 ThreadLocal ThreadLocal 是 Java 并发包中的一个小工具,它允许我们创建本地线程变量。通俗点说,就是为每个线程创建一个自身独有的变量,每个线程只能访问自己独有的变量,而对于其他线程的变量是无法访问的。可以随时设置或获取本地线程变量的值,每个线程的操作都是相互独立的。 …

    多线程 2023年5月16日
    00
  • python多进程和多线程介绍

    Python多进程和多线程是Python并发编程的核心内容,可以充分利用多核CPU资源,提高程序执行效率。下面是Python多进程和多线程的详细介绍及示例说明: 多进程 多进程指的是在一个应用程序中启动多个进程,每个进程各自独立运行。主要特点包括: 每个进程独立运行,相互之间不会影响 各进程之间可以使用IPC(进程间通信)实现数据共享 以下是Python多进…

    多线程 2023年5月16日
    00
  • Java多线程的具体介绍与使用笔记小结

    Java多线程的具体介绍与使用 什么是多线程 多线程指的是在同一时间内,CPU运行多个线程来完成不同的任务。在Java中,每个线程都是独立的执行路径,使得程序可以分配更多的资源去处理其他任务,并确保线程之间的相互独立。 多线程的优点 多线程的优点主要体现在以下几个方面: 实现并发编程,提升代码的效率和性能; 减少线程资源的竞争,提高程序的响应性和稳定性; 分…

    多线程 2023年5月17日
    00
  • Python多线程正确用法实例解析

    Python多线程正确用法实例解析 Python中的多线程可以提高程序的性能,但是在使用多线程时需要注意一些细节问题,避免出现错误。本篇文章将讲解Python多线程的正确用法,并给出两个示例来说明多线程的应用。 多线程简介 线程是程序执行的最小单元,多线程指的是程序同时执行多个线程来完成任务,可以提高程序执行效率。Python中的_thread模块和thre…

    多线程 2023年5月17日
    00
  • 一文详解如何有效的处理Promise并发

    一文详解如何有效的处理Promise并发 在JavaScript的异步编程中,Promise是一种广泛使用的方式,它能很好地解决回调地狱问题,提高代码的可读性和可维护性。然而,在实际应用中,也会遇到需要同时执行多个Promise的场景,这就需要我们学会如何处理Promise并发。 1. Promise并发的几种基本方式 在处理Promise并发时,主要有以下…

    多线程 2023年5月17日
    00
  • Java并发编程之volatile与JMM多线程内存模型

    Java并发编程之volatile与JMM多线程内存模型 什么是多线程内存模型 多线程内存模型是描述多个线程执行程序时,各自对内存读写操作的行为规定。Java中的多线程内存模型简称JMM。JMM描述了Java虚拟机(JVM)在运行多线程程序时,线程之间如何进行通信、数据之间如何同步等问题。它规定了一个线程在什么情况下可以看到另一个线程对共享变量所做的修改。 …

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