CountDownLatch 和 CyclicBarrier的区别与详解

【一线大厂Java面试题合集】第27篇-JUC并发工具类详解 Phaser 是 JDK 7 引入的更灵活的同步屏障工具,可以看作是 CountDownLatch 和 CyclicBarrier 的增强版。动态注册:运行时动态增加/减少参与方数量多阶段同步:支持多个阶段(phase)的协调,每个阶段可以有不同的参与者分层结构:支持 Phaser 树状分层,减少竞争可自定义行为:通过重写来自定义阶段到达时的行为工具类核心作用底层实现可复用典型场景等待 N 个事件完成AQS 共享模式否服务启动等待初始化N 个线程互相等待是多线程分阶段计算。 阅读详情

一.CountDownLatch 和 CyclicBarrier的区别

  1. CountDownLatch和CyclicBarrier都是线程同步的工具类,都是基于AQS实现的;
  2. CountDownLatch 的计数器是大于或等于线程数的,而CyclicBarrier是一定等于线程数;
  3. CountDownLatch 放行由其他线程控制而CyclicBarrier是由本身来控制的,CountDownLatch允许一个或多个线程一直等待,直到这些线程完成它们的操作,而CyclicBarrier不一样,它往往是当线程到达某状态后,暂停下来等待其他线程,等到所有线程均到达以后,才继续执行,二者的等待主体是不一样的;
  4. CountDownLatch调用await()通常是主线程/调用线程,而CyclicBarrier调用await()是在任务线程调用的;
  5. CountDownLatch 操作的是事件,阻塞足够多的次数即可,不管几个线程;而 CyclicBarrier 侧重点是线程,强调多个线程间互相等待,同时结束;
  6. CountDownLatch 是不可以重置的,所以无法重用;而 CyclicBarrier 则没有这个限制,可以重用;

二.详解

CountDownLatch是通过计数器实现,每次完成一个任务后,计数器减一当为0时,CountDownLatch.await()方法的线程就可以恢复执行任务。

CountDownLatch是基于AQS实现的,它的实现机制很简单,当我们在构建CountDownLatch对象时,传入的值其实就会赋值给 AQS 的关键变量state,执行countDown方法时,其实就是利用CAS 将state 减一,执行await方法时,其实就是判断state是否为0,不为0则加入到队列中,将该线程阻塞掉(除了头结点),因为头节点会一直自旋等待state为0,当state为0时,头节点把剩余的在队列中阻塞的节点也一并唤醒。

CyclicBarrier是直接借助ReentrantLock加上Condition 等待唤醒的功能 进而实现的,在构建CyclicBarrier时,传入的值会赋值给CyclicBarrier内部维护count变量,也会赋值给parties变量(这是可以复用的关键),每次调用await时,会将count -1 ,操作count值是直接使用ReentrantLock来保证线程安全性,如果count不为0,则添加则condition队列中,如果count等于0时,则把节点从condition队列添加至AQS的队列中进行全部唤醒,并且将parties的值重新赋值为count的值(实现复用)

总结

CountDownlatch基于AQS实现,会将构造CountDownLatch的入参传递至state,countDown()就是在利用CAS将state减-1,await()实际就是让头节点一直在等待state为0时,释放所有等待的线程
CyclicBarrier则利用ReentrantLock和Condition,自身维护了count和parties变量。每次调用await将count-1,并将线程加入到condition队列上。等到count为0时,则将condition队列的节点移交至AQS队列,并全部释放。

用法

CountDownLatch 用法

从代码层面,CountDownLatch 的用法是:

// 设置10个计数 
CountDownLatch countDownLatch = new CountDownLatch(10); 
// 每次调用即可减1 
countDownLatch.countDown(); 
// 其他线程一直等待减到0后,才继续执行 
countDownLatch.await()

举个栗子:
假设有一个业务场景,我们要求把所有的图片上传到文件服务器,然后将图片的地址URL保存到数据库;
其中上传素材,我们可以使用多线程去上传,都上传完之后,再入库。

publicbooleandealVedoi(List<Vedio>vedioList){
	//每个线程处理的最大任务数
	intmaxNum=10;
	
	intthreadNums=0;
	Map<String,String>map=newConcurrentHashMap<String,String>((int)(vedioList.size()/0.75));
	
	if(vedioList.size()<maxNum){
		threadNums=1;
	}else{
		//获取当前系统可用的处理器核心数量
		threadNums=Runtime.getRuntime().availableProcessors()>vedioList.size()/maxNum?
		vedioList.size()/maxNum:Runtime.getRuntime().availableProcessors();
	}
	
	try{
		//创建固定线程数处理这批任务
		ExecutorServiceexecutor=Executors.newFixedThreadPool(threadNums);
		
		CountDownLatchcountDownLatch=newCountDownLatch(vedioList.size());
		
		Iterator<Vedio>iterator=vedioList.iterator();
		while(iterator.hasNext()){
			executor.submit(()->{
				Vediovedio=iterator.next();
				Stringurl=store(vedio);
				map.put(vedio.getName());
				countDownLatch.countDown();
			});
		}
		
		countDownLatch.await();
		
		//所有素材上传成功后,入库
		saveDataBase(map);
	}catch(InterruptedExceptione){
		e.printStackTrace();
	}
}

newFixedThreadPool 方法用于创建一个固定大小的线程池,其中参数指定线程池的大小(即线程数量)。

适合的线程池大小取决于你的具体需求和应用场景。以下几点是需要考虑的因素:

  1. 任务的性质: 如果你的任务是 CPU 密集型的(需要大量的计算和处理),那么线程池的大小通常与处理器的核心数相近或略多一些可能是合适的。这样可以充分利用 CPU 资源。如果任务是 I/O 密集型的(例如涉及网络请求或文件操作),则可能需要更多的线程,以充分利用等待 I/O 的时间。
  2. 可用的系统资源: 考虑可用的系统资源,包括 CPU 核心数、内存和其他正在运行的应用程序。如果系统资源有限,将线程池大小保持在合理的范围内,以避免过度消耗资源。
  3. 任务的数量和规模: 考虑任务的数量和规模。如果你预计会有大量的任务需要处理,并且这些任务是短暂的,那么增加线程池的大小可以提高并发处理能力。但是,如果任务的数量较少或任务的执行时间较长,可能不需要太多的线程。
    需要注意的是,如果线程池的大小设置过大,可能会导致资源竞争、上下文切换开销增加,甚至对系统性能产生负面影响。因此,需要根据实际情况进行调整和测试,找到适合你应用程序的线程池大小。
    综合考虑以上因素,你可以根据你的应用需求和性能测试来选择一个合适的线程池大小。通常情况下,线程池大小在 2 到 10 之间是一个常见的范围。根据实际情况进行调整和优化是最佳的做法。
CyclicBarrier 用法

从代码使用角度来说:

// 初始化值为5的栅栏 
CyclicBarrier cyclicBarrier = new CyclicBarrier(5); 
// 每个线程调用 await()
cyclicBarrier.await(); 
// 等到有 5 个线程都执行了 await() 之后,继续执行。 
// 并且 栅栏的 计数器会自动重置为 5 ,可以接着用

然后我们模拟一个场景
在游戏中,选好英雄之后,会等待所有 5 个玩家进度条都到 100% 才开始游戏,我们可以使用 CyclicBarrier 来模拟这个场景

publicclassCyclicBarrierTest{
	privatefinalstaticExecutorServiceEXECUTOR_SERVICE=Executors.newFixedThreadPool(5);
	privatefinalstaticCyclicBarrierBARRIER=newCyclicBarrier(10);
	
	publicstaticvoidmain(String[]args){
		for(inti=0;i<5;i++){
			finalStringname="玩家"+i;
			
			EXECUTOR_SERVICE.execute(newRunnable(){
			
				@Override
				publicvoidrun(){
					try{
						Thread.sleep(2000);
						System.out.println(name+"已准备,等待其他玩家准备...");
						BARRIER.await();
						Thread.sleep(1000);
						System.out.println(name+"已加入游戏");
					}catch(InterruptedExceptione){
						System.out.println(name+"离开游戏");
					}catch(BrokenBarrierExceptione){
						System.out.println(name+"离开游戏");
					}
				}
			});
		}
		EXECUTOR_SERVICE.shutdown();
	}
}
手把手教你用THS4551搭建全差分放大器电路(附ADC驱动实战) 本文详细介绍了如何使用TI的THS4551全差分放大器搭建高性能ADC驱动电路,涵盖芯片选型、电路配置、PCB布局及实战调试等关键环节。THS4551凭借其优异的共模抑制比和宽电源电压范围,成为驱动16位及以上精度ADC的理想选择,特别适合工业应用场景。 阅读详情

相关推荐

告别手动复制粘贴!用Python脚本+pywinauto实现PC微信消息自动发送(附完整源码)

本文详细介绍了如何利用Python和pywinauto实现PC微信消息的自动化发送,告别繁琐的手动操作。从环境搭建、UI控件定位到构建健壮的发送流程,再到高级功能扩展和项目打包部署,全面解析了自动化办公的实现方案,显著提升工作效率。

weixin_30315723的博客 583

CountDownLatch和CyclicBarrier有什么区别?

3.CyclicBarrier提供getNumberWaiting()方法,可以获得CyclicBarrier阻塞的线程数量,还提供isBroken()方法,可以判断阻塞的线程是否被中断,等等。2.CyclicBarrier能处理更为复杂的业务场景,比如计算发生错误,可以结束阻塞,重置计算器,重新执行程序。4.CountDownLatch会阻塞主线程,CyclicBarrier不会阻塞主线程,只会阻塞子线程。

mischen520的博客 925

【微知】关于GB200 NVL72服务器的一些信息?(36CPU72GPU;LPDDR5X 17T;HBM3e 13.5T;5代NVlink 1.8TB; 720P算力FP8;120Kw)

本文仅根据官网介绍分析,存在纰漏仅供参考。

技术札记 5382

java并发-CountDownLatch和CyclicBarrier区别、简单使用demo

文章目录CountDownLatch和CyclicBarrier区别 CountDownLatch和CyclicBarrier区别 CountdownLatch和CyclicBarrier的区别使用场景与具体实现 参考URL: https://zhuanlan.zhihu.com/p/139020914 CountDownLatch和CyclicBarrier使用上的区别 参考URL: https://www.cnblogs.com/geekdc/p/11541266.html CountDownLatch

西京刀客 3333

手把手教你用Simulink给C2000配置SCI串口发送数据(附模型与避坑点)

本文详细介绍了如何使用Simulink为C2000系列微控制器配置SCI串口发送数据,包括硬件资源分配、模型搭建、参数设置及调试技巧。通过代码生成和串口通信实践,帮助开发者高效实现嵌入式系统开发,避免常见通信问题。

weixin_30831529的博客 294

Vivado与VCS+Verdi联合仿真环境搭建全攻略

本文详细介绍了如何搭建Vivado与VCS+Verdi联合仿真环境,旨在解决Vivado Simulator在大型FPGA验证中速度慢、调试弱的问题。通过指导工具版本配对、环境变量设置、关键参数配置及Xilinx仿真库编译,帮助工程师高效整合Vivado的设计管理、VCS的高速仿真与Verdi的深度调试能力,从而显著提升验证效率。

weixin_29219189的博客 576

【同步工具】CyclicBarrier和CountDownLatch的区别

一旦所有线程都到达了屏障点,CyclicBarrier 将会释放所有被阻塞的线程,它们将。是 CyclicBarrier 类中的一个方法,用于使当前线程等待直到所有线程都到达屏障点。计数器可以重复使用,一旦计数器归零,会触发一次屏障操作,然后计数器重新初始化。方法被调用后,当前线程会被阻塞,直到所有参与的线程都调用了 await()适用于多个线程相互等待,直到所有线程都到达一个公共的屏障点后再继续执行。每个线程等待其他所有线程都到达屏障点后再继续执行。计数器只能递减,一旦计数器归零,就无法重置。

WaaTong的博客 1307

uniapp+华为HBuilder X 4.29跑鸿蒙模拟器报错没有签名授权

uniapp+华为HBuilder X 4.29跑鸿蒙模拟器报错没有签名授权报错信息11:39:47.976 安装 .hap 到鸿蒙设备 ...11:39:48.517 运行所需的权限没有签名授权,请参考 配置文档11:39:48.517 安装失败。

weixin_66071584的博客 1350

CountDownLatch和CyclicBarrier区别详解

一、CountDownLatch CountDownLatch:是个门闩,当倒数为0,即其他线程全都执行到某一处时,释放某一主线程运行(也可为某一个其他线程)。例子如下: 没加CountDownLatch: import java.util.concurrent.CountDownLatch; public class CountDownLatchDemo { public static ...

weixin_43896829的博客 266

嵌入式开发必看:STM32 DMA双缓冲配置全攻略(含CubeMX教程)

本文详细解析了STM32 DMA双缓冲机制的原理与优势,并提供了基于CubeMX的完整配置教程。通过硬件自动切换两个缓冲区,实现DMA传输与CPU处理的真正并行,有效降低中断频率,提升高速数据采集、音频流处理等场景下的系统效率和实时性。

weixin_29212429的博客 173

Tomcat漏洞——弱口令爆破

靶机:CentOS7 IP:192.168.100.40。攻击机:kali IP:192.168.100.60。版 权 声 明:本博客所有文章除特别声明外,均采用。文章版权归作者所有,未经允许请勿转载!作 者:PeiyuJue。

weixin_57379923的博客 909

CountDownLatch类 和 CyclicBarrier类 详解与区别

1. CountDownLatch 类 CountDownLatch 类是用于线程同步的工具,作用:让一个或多个源线程(调用await方法的线程) 必须 等待一个或多个目标线程(调用countDown方法的线程)都执行完成了才能继续执行自己的代码。 注意: 1. 不会妨碍目标线程的执行,但是会阻塞源线程,因为await方法会检测count是为0,如果不是0,就会阻塞,不会继续执行后面的代码。...

dgh112233的博客 511

【YOLOv8科研级创新】集成HS-FPN特征融合网络,让Neck模块在参数量锐减100W的同时精度跃升

打开确保模型解析器能识别HS_FPN模块。通过将HS-FPN集成到YOLOv8中,我们实现了一个“轻量级多尺度特征融合+精准检测”的目标检测模型。这个改进不仅在工程上能提升多尺度、细粒度场景的检测效果并降低部署成本,更在科研上提供了“选择性轻量级特征融合”的创新思路——这种思路可以延伸到其他检测网络(如Faster R-CNN、SSD)的Neck模块改进中,帮你在论文中打造独特的研究点。

m0_64661770的博客 137

CountDownLatch 与 CyclicBarrier:区别、源码与实战详解

摘要 Java并发工具CountDownLatch与CyclicBarrier的核心区别在于:CountDownLatch采用一次性递减计数器机制,主线程等待多个子线程完成任务;而CyclicBarrier使用可重复的屏障机制,多线程互相等待达到同步。前者适用于启动前等待资源初始化等场景,后者适合分阶段并行计算。两者底层实现不同,CountDownLatch基于AQS,CyclicBarrier使用ReentrantLock和Condition。正确选择取决于具体场景需求。

ywl470812087的博客 280

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

cyclicbarrier countdownlatch java_详解java CountDownLatch和CyclicBarrier在内部实现和场景上的区别...

前言CountDownLatch和CyclicBarrier两个同为java并发编程的重要工具类,它们在诸多多线程并发或并行场景中得到了广泛的应用。但两者就其内部实现和使用场景而言是各有所侧重的。内部实现差异前者更多依赖经典的AQS机制和CAS机制来控制器内部状态的更迭和计数器本身的变化,而后者更多依靠可重入Lock等机制来控制其内部并发安全性和一致性。public class {//Synchr...

weixin_32331453的博客 139

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

【Java并发编程实战】CountDownLatch、CyclicBarrier、Semaphore 的区别详解

重置计数,抛出BrokenBarrierException。一次性使用,计数到0后失效。递减(countDown)多个线程互相等待到达屏障。等待多个线程完成任务。可循环使用,自动重置。

gaochufukanyongren的博客 341

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

java barrier latch_详解java CountDownLatch和CyclicBarrier在内部实现和场景上的区别

前言CountDownLatch和CyclicBarrier两个同为java并发编程的重要工具类,它们在诸多多线程并发或并行场景中得到了广泛的应用。但两者就其内部实现和使用场景而言是各有所侧重的。内部实现差异前者更多依赖经典的AQS机制和CAS机制来控制器内部状态的更迭和计数器本身的变化,而后者更多依靠可重入Lock等机制来控制其内部并发安全性和一致性。public class {//Synchr...

weixin_29952601的博客 240

并发工具类使用详解及区别(CountDownLatch、CyclicBarrier、Semaphore、Exchanger)

本文转载自:码农历险记 CountDownLatch CountDownLatch介绍 CountDownLatch是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程执行完后再执行。例如,应用程序的主线程希望在负责启动框架服务的线程已经启动所有框架服务之后执行。 CountDownLatch 是通过一个计数器来实现的,计数器的初始化值为线程的数量。每当一个线程完成了自己的任务后...

赵英超的博客 1289

CyclicBarrier和CountDownLatch区别

两个类都在java.util.concurrent包下,都可以用来表示代码运行在某个点上,二者的区别在于: 1)CyclicBarrier的某个线程运行在某个点上之后,该线程即停止运行,直到所有的线程都达到了这个点,所有线程才重新运行; CountDownLatch则不是,某县城运行在某个点上之后,只是给某个数值-1而已,该线程继续运行。 2)CyclicBarrier只能唤起一个任务,Co...

weixin_36509612的博客 205

Java面试题:请解释内存泄漏的原因,并说明如何使用Thread类和ExecutorService实现多线程编程,请解释CountDownLatch和CyclicBarrier在并发编程中的用途和区别

通过上述综合面试题的深度解析,我们不仅回顾了Java内存泄漏的原因和多线程编程的方法,还深入探讨了并发工具。

杰哥在此的专栏 351

AQS源码阅读感想

1.AQS核心原理 --AQS拥有变量state,通过CAS设定state得值是否成功判断是否获得锁,源码如下: compareAndSetState(c, nextc) protected final boolean compareAndSetState(int expect, int update) { return unsafe.compareAndSwapInt(thi...

idealemail的博客 172

并发和多线程

总结java并发和多线程的核心概念和知识点,以及开发时的注意事项。

Learning 597

java中的高并发

这个大概可以作为一个继续深究下去的引子。 首先得先理解并发与并行的含义,并行其实指的是串行并行,程序A和程序B交替执行,而从计算机cpu的执行时间来说,从人的感受上来说,就像是并行。 而并行一般就是在多核cpu的环境下,多个任务在同一时间在执行。 另外一个要清楚的概念就是,进程与线程的概念,进程是计算机资源分配和调度的最小单位,而线程是程序执行和调度的最小单位,进程就像是一间房子,这个房子里...

huangqing510的专栏 609
上一篇: IDEA源码下载失败问题
CodAlun
博客等级 码龄8年 46粉丝 96原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值