Java中的 CyclicBarrier详解

Java中的 CyclicBarrier详解

1. 什么是CyclicBarrier

CyclicBarrier是Java并发包中的一个类,可以让一组线程在某个条件达成时全部同时开始执行。简而言之,CyclicBarrier是一种同步机制,它允许指定的线程等待彼此到达某个同步点。

CyclicBarrier和CountDownLatch都可以用于线程间的同步,但它们之间也存在一些区别。CountDownLatch是一种能够使一个或多个线程等待一系列指定的任务执行完后再执行的同步机制,而CyclicBarrier是一种等待所有线程都满足某个条件后再继续执行的同步机制。

CyclicBarrier的用法非常简单,只需要在创建实例时指定同步点即可,线程在运行过程中到达同步点时将被阻塞,直到所有线程都到达同步点后才会一起继续执行。

2. CyclicBarrier常用方法

CyclicBarrier类提供了一些方法可以用于实现线程间的同步控制。

2.1 构造方法

CyclicBarrier的构造方法有两种基本形式:

public CyclicBarrier(int parties)

构造一个新的CyclicBarrier,它将在指定数量的线程(称为parties)等待之后启动执行。

public CyclicBarrier(int parties, Runnable barrierAction)

构造一个新的CyclicBarrier,它将在指定数量的线程等待之后启动执行,并会执行指定的Runnable。

2.2 await()

CyclicBarrier的唯一方法是await(),调用await()表示该线程已经到达了同步点。当某个线程调用await()时,它将会被阻塞,而其他线程继续执行,直到所有线程都到达了同步点。

public void await() throws InterruptedException, BrokenBarrierException;

2.3 reset()

CyclicBarrier还提供了reset()方法,用于重置同步点。在调用reset()方法后,所有已经在等待的线程都将抛出BrokenBarrierException异常。

public void reset();

3. CyclicBarrier的使用示例

下面的示例演示了如何使用CyclicBarrier来实现一批线程同时开始执行:


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

public class CyclicBarrierDemo {
    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(5, new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + " is working");
            }
        });

        for (int i = 0; i < 5; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + " is waiting");
                    try {
                        cyclicBarrier.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + " is working");
                }
            }, "Thread-" + i).start();
        }
    }
}

运行结果如下:

Thread-2 is waiting
Thread-3 is waiting
Thread-4 is waiting
Thread-0 is waiting
Thread-1 is waiting
Thread-2 is working
Thread-3 is working
Thread-4 is working
Thread-0 is working
Thread-1 is working

上面的代码中,我们创建了一个CyclicBarrier实例,其参数parties为5,表示要等待5个任务完成。在每一个线程中,我们先打印出当前线程正在等待,然后调用cyclicBarrier.await()方法将线程阻塞。当所有线程都到达了同步点后,会执行CyclicBarrier的构造方法中指定的Runnable,同时所有被阻塞的线程开始同步执行,打印出"Thread-x is working",x为线程的编号。

另一个示例演示了如何使用CyclicBarrier来模拟比赛的开始、进行和结束,其中比赛有三个阶段:准备、开始、结束。


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

public class RaceDemo {
    private static CyclicBarrier cyclicBarrier;

    public static void main(String[] args) throws InterruptedException {
        cyclicBarrier = new CyclicBarrier(4, new Runnable() {
            @Override
            public void run() {
                System.out.println("All the players are ready, let's start the game!");
            }
        });

        Player player1 = new Player("Tom");
        Player player2 = new Player("Jerry");
        Player player3 = new Player("Mike");
        Player player4 = new Player("John");

        player1.start();
        player2.start();
        player3.start();
        player4.start();

        player1.join();
        player2.join();
        player3.join();
        player4.join();
    }

    static class Player extends Thread {
        private String name;

        public Player(String name) {
            this.name = name;
        }

        @Override
        public void run() {
            try {
                System.out.println(name + " is preparing...");
                Thread.sleep(1000);
                cyclicBarrier.await();
                System.out.println(name + " starts running...");
                Thread.sleep(3000);
                cyclicBarrier.await();
                System.out.println(name + " is close to the finish line...");
                Thread.sleep(2000);
                cyclicBarrier.await();
                System.out.println(name + " crosses the finish line!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }
}

运行结果如下:

Tom is preparing...
Jerry is preparing...
Mike is preparing...
John is preparing...
All the players are ready, let's start the game!
Tom starts running...
Mike starts running...
Jerry starts running...
John starts running...
Jerry is close to the finish line...
Mike is close to the finish line...
Tom is close to the finish line...
John is close to the finish line...
Jerry crosses the finish line!
Mike crosses the finish line!
Tom crosses the finish line!
John crosses the finish line!

上面的代码中,我们创建了一个CyclicBarrier实例,其参数parties为4,表示等待4个运动员准备就绪后开始比赛。在每一个运动员中,我们通过cyclicBarrier.await()将每一个运动员线程阻塞,直到所有运动员都到达同步点。当所有运动员都准备就绪后,CyclicBarrier的构造方法中指定的Runnable开始执行,打印出"All the players are ready, let's start the game!",同时所有阻塞的线程开始继续执行比赛流程。当每一阶段都完成后,所有线程再次被阻塞,等待其他线程完成当前阶段。最后一阶段完成后,所有线程将一起结束比赛。

通过这两个示例,我们可以看到CyclicBarrier的强大功能和使用方法,它可以方便地实现线程之间的同步控制,很好地提高了并发编程的效率。

阅读剩余 75%

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java中的 CyclicBarrier详解 - Python技术站

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

相关文章

  • Java 配置log4j日志文件路径 (附-获取当前类路径的多种操作)

    下面是Java配置log4j日志文件路径的完整攻略。 1. 什么是log4j? log4j是Java开发中非常常用的日志工具,它可以方便地记录系统运行时的各种事件,同时也能够帮我们排查错误。在Java开发中使用log4j可以大大提高我们开发的效率。 2. 配置log4j日志文件路径 2.1 配置log4j.properties log4j的配置文件可以是XM…

    Java 2023年5月20日
    00
  • Java String类的常用方法汇总

    Java String类的常用方法汇总 String类概述 Java中的String类是用于操作字符串的常用类。其本质上是一个不可变的字符序列,也就是说,一旦创建了一个String对象,就无法再对其进行修改。 常用方法汇总 在日常开发中,String类的常用方法如下: 1. 字符串比较 equals(Object obj):比较两个字符串是否相等,区分大小写…

    Java 2023年5月26日
    00
  • SpringBoot封装JDBC的实现步骤

    下面是SpringBoot封装JDBC的实现步骤的完整攻略。 1. 添加依赖 首先,在SpringBoot的pom.xml文件中添加jdbc和mysql-connector-java的依赖: <dependency> <groupId>org.springframework.boot</groupId> <artif…

    Java 2023年5月20日
    00
  • 解析Java编程之Synchronized锁住的对象

    下面我将详细讲解“解析Java编程之Synchronized锁住的对象”的完整攻略。 介绍 在Java编程中,使用Synchronized关键字来进行同步控制是非常常见的路线。这个关键字提供了一种简单的方法来确保在并发代码的同时,一组代码只有一个线程可以访问。Synchronized关键字的目标对象是引用变量。 应用 要在Java编程中使用Synchroni…

    Java 2023年5月26日
    00
  • 基于Java Tomcat和激活MyEclips的深入理解

    基于Java Tomcat和激活MyEclipse的深入理解攻略 1. 安装Java Tomcat Java Tomcat是一款开源的Web服务器,支持Servlet和JavaServer Pages(JSP)技术。安装Java Tomcat十分简单,我们只需要到官网下载页面,下载我们需要的版本,然后解压即可。 2. 激活MyEclipse MyEclips…

    Java 2023年6月2日
    00
  • SpringMVC的五大核心组件用法及说明

    以下是关于“SpringMVC的五大核心组件用法及说明”的完整攻略,其中包含两个示例。 SpringMVC的五大核心组件用法及说明 SpringMVC是Spring框架的一个模块,它是一个基于MVC(Model-View-Controller)架构的Web框架,用于构建Web应用程序。SpringMVC的五大核心组件包括DispatcherServlet、H…

    Java 2023年5月16日
    00
  • 如何实现线程安全的算法?

    以下是关于线程安全的算法的完整使用攻略: 什么是线程安全的算法? 线程安全的算法是指在多线程环境下,多个线程可以同时访问算法而不会出现数据不一致或程序崩溃等问题。在线程编程中,线程安全的算法是非常重要的,因为多个线程同时访问算法,会出现线程争用的问题,导致数据不一致或程序崩溃。 如何实现线程安全的算法? 为实现线程安全的算法需要使用同步机制来保证多线程对算法…

    Java 2023年5月12日
    00
  • Java 中的 BufferedWriter 介绍_动力节点Java学院整理

    Java 中的 BufferedWriter 介绍 什么是 BufferedWriter BufferedWriter 是 Java.io 包中提供的一个字符缓冲输出流,它内部封装了一个字符缓冲区(Buffer),可以提高字符输出效率。 BufferedWriter 的构造方法 BufferedWriter 提供了两个构造方法: public Buffere…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部