【并发技术15】线程同步工具CyclicBarrier的使用

简介: 【并发技术15】线程同步工具CyclicBarrier的使用

我们知道,Semaphore 同步工具主要提供了一个记数信号量,允许最大线程数运行。CyclicBarrier 是另一个同步工具,本文主要来总结一下 CyclicBarrier 的使用。先看一下官方的对 CyclicBarrier 的介绍:

一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。

我的解释是这样的:

CyclicBarrier 可以使不同的线程彼此等待,在不同的线程都执行完了后,再执行下面的程序。比如A、B、C三个同学要去玩,大巴在校门口,A、B、C分别从各自的寝室出来,先后到达大巴处,先来的必须等待,直到三个同学都来了,大巴才能走。他们要玩两个地方M和N,到了M处,三个同学又各自去玩了,玩完后各自回到大巴上,先回来的必须等待,直到三个同学都到了,大巴才能到N处,这个大巴可以循环利用。这个大巴就是 CyclicBarrier。

CyclicBarrier 同步工具相对来说比较简单,因为功能很明确,下面写一个 CyclicBarrier 的示例代码:

public class CyclicBarrierTest {
    public static void main(String[] args) {
        ExecutorService service = Executors.newCachedThreadPool();
        final CyclicBarrier cb = new CyclicBarrier(3); //设置要三个线程等待,都执行完了再往下执行
        System.out.println("初始化:当前有" + (cb.getNumberWaiting() + "个线程在等待"));
         //3个任务
        for (int i = 0; i < 3; i++) {
            Runnable run = new Runnable() {  
                public void run() {  
                    try {  
                        Thread.sleep((long)(Math.random()*10000));  
                        System.out.println(Thread.currentThread().getName() 
                                + "即将到达集合点1,当前已有" + (cb.getNumberWaiting()+1) + "个线程到达,"
                                + (cb.getNumberWaiting()==2?"都到齐了,去集合点2!":"正在等候……"));  
                        // 访问完后,释放 ,如果屏蔽下面的语句,则在控制台只能打印3条记录,之后线程一直阻塞
                        cb.await(); //等待 
                        Thread.sleep((long)(Math.random()*10000));  
                        System.out.println(Thread.currentThread().getName() 
                                + "即将到达集合点2,当前已有" + (cb.getNumberWaiting()+1) + "个线程到达,"
                                + (cb.getNumberWaiting()==2?"都到齐了,去集合点3!":"正在等候……"));   
                        cb.await();
                        Thread.sleep((long)(Math.random()*10000));  
                        System.out.println(Thread.currentThread().getName() 
                                + "即将到达集合点3,当前已有" + (cb.getNumberWaiting()+1) + "个线程到达,"
                                + (cb.getNumberWaiting()==2?"都到齐了,执行完毕!":"正在等候……"));  
                        cb.await();
                    } catch (Exception e) {  
                    }  
                }  
            };  
            service.execute(run);  //执行任务
        }  
        service.shutdown(); //关闭线程
    }
}


从代码中可以看出,CyclicBarrier 的使用主要有两点,一是初始化,二是调用 await() 方法。这个 await() 方法也就是官方解释中的“公共屏障点”,到了这个点,所有线程都得等待,直到规定数量的线程全部到达才能往下执行。看一下运行效果:

初始化:当前有0个线程在等待

pool-1-thread-3即将到达集合点1,当前已有1个线程到达,正在等候……

pool-1-thread-2即将到达集合点1,当前已有2个线程到达,正在等候……

pool-1-thread-1即将到达集合点1,当前已有3个线程到达,都到齐了,去集合点2!

pool-1-thread-2即将到达集合点2,当前已有1个线程到达,正在等候……

pool-1-thread-3即将到达集合点2,当前已有2个线程到达,正在等候……

pool-1-thread-1即将到达集合点2,当前已有3个线程到达,都到齐了,去集合点3!

pool-1-thread-3即将到达集合点3,当前已有1个线程到达,正在等候……

pool-1-thread-1即将到达集合点3,当前已有2个线程到达,正在等候……

pool-1-thread-2即将到达集合点3,当前已有3个线程到达,都到齐了,执行完毕!

CyclicBarrier 的应用场合也很明显:在某种需求中,比如一个大型的任务,常常需要分配好多子任务去执行,只有当所有子任务都执行完成时候,才能执行主任务,这时候,就可以选择CyclicBarrier 了。

可以再确切一点:假如我们需要统计全国的业务数据,其中各省的数据库是独立的,也就是说按省分库。并且统计的数据量很大,统计过程也比较慢。为了提高性能,快速计算。我们采取并发的方式,多个线程同时计算各省数据,最后再汇总统计,在这里 CyclicBarrier 就非常有用。


相关文章
|
1月前
|
并行计算 Java 数据处理
SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析
SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析
169 0
|
27天前
|
安全
List并发线程安全问题
【10月更文挑战第21天】`List` 并发线程安全问题是多线程编程中一个非常重要的问题,需要我们认真对待和处理。只有通过不断地学习和实践,我们才能更好地掌握多线程编程的技巧和方法,提高程序的性能和稳定性。
131 59
|
6天前
|
安全 Java 开发者
Java 多线程并发控制:深入理解与实战应用
《Java多线程并发控制:深入理解与实战应用》一书详细解析了Java多线程编程的核心概念、并发控制技术及其实战技巧,适合Java开发者深入学习和实践参考。
|
21天前
|
安全 程序员 API
|
18天前
|
存储 设计模式 分布式计算
Java中的多线程编程:并发与并行的深度解析####
在当今软件开发领域,多线程编程已成为提升应用性能、响应速度及资源利用率的关键手段之一。本文将深入探讨Java平台上的多线程机制,从基础概念到高级应用,全面解析并发与并行编程的核心理念、实现方式及其在实际项目中的应用策略。不同于常规摘要的简洁概述,本文旨在通过详尽的技术剖析,为读者构建一个系统化的多线程知识框架,辅以生动实例,让抽象概念具体化,复杂问题简单化。 ####
|
25天前
|
存储 安全 UED
多线程在打包工具中的运用
【11月更文挑战第2天】本文介绍了多线程技术在打包工具中的应用,包括提高打包效率、优化用户体验和多线程安全考虑。通过并行处理文件和加速资源收集,多线程可以显著缩短打包时间。在用户体验方面,多线程使界面保持响应,并支持优先级处理。此外,文章还讨论了资源访问冲突和死锁预防的解决方案,确保多线程环境下的稳定性和安全性。
|
1月前
|
Java
【编程进阶知识】揭秘Java多线程:并发与顺序编程的奥秘
本文介绍了Java多线程编程的基础,通过对比顺序执行和并发执行的方式,展示了如何使用`run`方法和`start`方法来控制线程的执行模式。文章通过具体示例详细解析了两者的异同及应用场景,帮助读者更好地理解和运用多线程技术。
29 1
|
1月前
|
网络协议 安全 Java
难懂,误点!将多线程技术应用于Python的异步事件循环
难懂,误点!将多线程技术应用于Python的异步事件循环
64 0
|
2月前
|
网络协议 C语言
C语言 网络编程(十四)并发的TCP服务端-以线程完成功能
这段代码实现了一个基于TCP协议的多线程服务器和客户端程序,服务器端通过为每个客户端创建独立的线程来处理并发请求,解决了粘包问题并支持不定长数据传输。服务器监听在IP地址`172.17.140.183`的`8080`端口上,接收客户端发来的数据,并将接收到的消息添加“-回传”后返回给客户端。客户端则可以循环输入并发送数据,同时接收服务器回传的信息。当输入“exit”时,客户端会结束与服务器的通信并关闭连接。
|
2月前
|
数据采集 消息中间件 并行计算
进程、线程与协程:并发执行的三种重要概念与应用
进程、线程与协程:并发执行的三种重要概念与应用
60 0