【JAVA并发编程专题】同步屏障CyclicBarrier的理解和使用

简介: 【JAVA并发编程专题】同步屏障CyclicBarrier的理解和使用

正文


一、同步屏障简介


同步屏障CyclicBarrie的作用顾名思义,就是为所有线程设置一个屏障,等大家都同步后,再一起往下执行。比如我们有3个线程A、B、C,都启动后,势必有执行快慢的区别,我们为每个线程设置一个同步点,称为同步屏障。每个线程达到自己的这个同步点之后就进入等待状态,等待最后一个线程也达到同步点之后,大家再从同步点开始往后执行。


二、同步屏障的使用


    public static void main(String[] args) throws BrokenBarrierException, InterruptedException {
        // 设置屏障拦截的线程数量为2
        CyclicBarrier cyclicBarrier = new CyclicBarrier(2);
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                log.info("子线程开始执行...");
                try {
                    cyclicBarrier.await();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                log.info("子线程执行结束");
            }
        });
        thread.start();
        log.info("主线程开始执行...");
        TimeUnit.SECONDS.sleep(3);
        cyclicBarrier.await();
        log.info("主线程执行结束");
    }
}


执行结果为:

22:35:29.751 [main] INFO com.example.concurrent.CyclicBarrierTest - 主线程开始执行...
22:35:29.751 [Thread-0] INFO com.example.concurrent.CyclicBarrierTest - 子线程开始执行...
22:35:32.765 [main] INFO com.example.concurrent.CyclicBarrierTest - 主线程执行结束
22:35:32.765 [Thread-0] INFO com.example.concurrent.CyclicBarrierTest - 子线程执行结束

如果上述设置的拦截线程数量为3,那么主线程和子线程达到各自的同步点的时候,都不能再继续往下执行,而是一直再等待着。

还有一种用法,允许子线程在达到自己的同步点的时候,优先去执行另外一个任务,等到这个任务处理完成,子线程和主线程再同步往下执行。

public static void main(String[] args) throws BrokenBarrierException, InterruptedException {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(2, new MyThread());
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                log.info("子线程开始执行...");
                try {
                    cyclicBarrier.await();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                log.info("子线程执行结束");
            }
        });
        thread.start();
        log.info("主线程开始执行...");
        TimeUnit.SECONDS.sleep(2);
        cyclicBarrier.await();
        log.info("主线程执行结束");
    }
    static class MyThread implements Runnable{
        @Override
        public void run() {
            log.info("myThread运行开始...");
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("myThread运行结束");
        }
    }

输出结果如下:

02:16:16.289 [Thread-0] INFO com.example.concurrent.CyclicBarrierTest - 子线程开始执行...
02:16:16.295 [Thread-0] INFO com.example.concurrent.CyclicBarrierTest - myThread运行开始...
02:16:21.296 [Thread-0] INFO com.example.concurrent.CyclicBarrierTest - myThread运行结束
02:16:21.296 [Thread-0] INFO com.example.concurrent.CyclicBarrierTest - 子线程执行结束
02:16:21.297 [main] INFO com.example.concurrent.CyclicBarrierTest - 主线程执行结束

这里的MyThread主要是用来对子线程到达同步点时的运算结果做一些额外的处理工作。


三、CyclicBarrier和CountDownLatch的比较


  • 使用场景不同,CountDownLatch是主线程等待子线程全部countDown之后才可以继续工作,但是不会阻碍子线程的运行;CyclicBarrier是所有线程都到达自己的同步点之后,再一起从各自的同步点往后执行,在这之前,只要有一个线程没有达到同步点,大家都必须等着;
  • CountDownLatch是通过减法计数来实现的,每个计数只能使用一次,不能重复使用;而CyclicBarrier的计数是可以通过reset来重置的,如此可以重复使用,从而能处理更加复杂的业务场景,比如某个线程计算出现错误,可以重置计数,再执行一遍。


相关文章
|
1天前
|
缓存 Java 调度
Java中的多线程编程:从基础到实践
【10月更文挑战第24天】 本文旨在为读者提供一个关于Java多线程编程的全面指南。我们将从多线程的基本概念开始,逐步深入到Java中实现多线程的方法,包括继承Thread类、实现Runnable接口以及使用Executor框架。此外,我们还将探讨多线程编程中的常见问题和最佳实践,帮助读者在实际项目中更好地应用多线程技术。
9 3
|
3天前
|
监控 安全 Java
Java多线程编程的艺术与实践
【10月更文挑战第22天】 在现代软件开发中,多线程编程是一项不可或缺的技能。本文将深入探讨Java多线程编程的核心概念、常见问题以及最佳实践,帮助开发者掌握这一强大的工具。我们将从基础概念入手,逐步深入到高级主题,包括线程的创建与管理、同步机制、线程池的使用等。通过实际案例分析,本文旨在提供一种系统化的学习方法,使读者能够在实际项目中灵活运用多线程技术。
|
4天前
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第22天】在Java的世界里,对象序列化和反序列化是数据持久化和网络传输的关键技术。本文将带你了解如何在Java中实现对象的序列化与反序列化,并探讨其背后的原理。通过实际代码示例,我们将一步步展示如何将复杂数据结构转换为字节流,以及如何将这些字节流还原为Java对象。文章还将讨论在使用序列化时应注意的安全性问题,以确保你的应用程序既高效又安全。
|
1天前
|
缓存 安全 Java
Java中的多线程编程:从基础到实践
【10月更文挑战第24天】 本文将深入探讨Java中的多线程编程,包括其基本原理、实现方式以及常见问题。我们将从简单的线程创建开始,逐步深入了解线程的生命周期、同步机制、并发工具类等高级主题。通过实际案例和代码示例,帮助读者掌握多线程编程的核心概念和技术,提高程序的性能和可靠性。
7 2
|
2天前
|
Java
Java中的多线程编程:从基础到实践
本文深入探讨Java多线程编程,首先介绍多线程的基本概念和重要性,接着详细讲解如何在Java中创建和管理线程,最后通过实例演示多线程的实际应用。文章旨在帮助读者理解多线程的核心原理,掌握基本的多线程操作,并能够在实际项目中灵活运用多线程技术。
|
2天前
|
Java 程序员 开发者
Java编程中的异常处理艺术
【10月更文挑战第24天】在Java的世界里,代码就像一场精心编排的舞蹈,每一个动作都要精准无误。但就像最完美的舞者也可能踩错一个步伐一样,我们的程序偶尔也会遇到意外——这就是所谓的异常。本文将带你走进Java的异常处理机制,从基本的try-catch语句到高级的异常链追踪,让你学会如何优雅地处理这些不请自来的“客人”。
|
1天前
|
Java 调度
Java 线程同步的四种方式,最全详解,建议收藏!
本文详细解析了Java线程同步的四种方式:synchronized关键字、ReentrantLock、原子变量和ThreadLocal,通过实例代码和对比分析,帮助你深入理解线程同步机制。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
Java 线程同步的四种方式,最全详解,建议收藏!
|
4天前
|
Java 数据处理 开发者
Java多线程编程的艺术:从入门到精通####
【10月更文挑战第21天】 本文将深入探讨Java多线程编程的核心概念,通过生动实例和实用技巧,引导读者从基础认知迈向高效并发编程的殿堂。我们将一起揭开线程管理的神秘面纱,掌握同步机制的精髓,并学习如何在实际项目中灵活运用这些知识,以提升应用性能与响应速度。 ####
19 3
|
2天前
|
设计模式 SQL 安全
Java编程中的单例模式深入解析
【10月更文挑战第24天】在软件工程中,单例模式是设计模式的一种,它确保一个类只有一个实例,并提供一个全局访问点。本文将探讨如何在Java中使用单例模式,并分析其优缺点以及适用场景。
6 0
|
3天前
|
存储 Java
在Java编程的世界里,标识符命名是一项基础且至关重要的技能
在Java编程的世界里,标识符命名是一项基础且至关重要的技能
8 0