采访一个工作了5年的朋友,被问到这样一个问题,说,CountdownLatch和CycliBarriar有什么区别?这个对于很多人来说比较陌生,但是对于接触过并发编程的人来说还是比较简单的。今天,我就和大家分享一下我对这个问题的理解。1.CountdownLatch先来看CountDownLatch,它是一个复合词。CountDown是倒计时的意思,Latch是门闩的意思,又译为发令枪。在JDK注释中是这样的:一种同步辅助,允许一个或多个线程等待,直到其他线程中正在执行的一组操作完成。翻译过来就是让一个或多个线程继续等待,直到其他多线程执行的一组操作完成,这些等待的线程才会继续执行。就好比,一场百米赛跑,参赛的选手很多,裁判需要等所有选手都做好准备,在同一个起跑线上。接着,裁判会发出命令:“大家准备跑。”随着发令枪响起,所有选手都可以开始。在这个场景中,参赛者是线程,裁判是CountDownLatch。在我们实际开发中,有两种使用场景可以用CountDownLatch实现:(1)单线程等待多线程的场景。比如一个服务需要从多个远程接口获取数据,我们可以创建多个线程分别调用远程接口,等待所有的远程接口都获取到返回的数据,然后主服务线程继续执行。像并发计算、结果聚合等。(2)多线程等待的场景。比如模拟秒杀场景,让一组线程同时等待,同时恢复执行,从而达到最大的并行度。需要注意的是,当有高并发请求时,Countdownlatch的await方法可能会造成死锁。如果线程池线程数少,高并发时多个请求会占用所有线程,但每个请求都需要await()其他线程,等待的线程得不到线程资源无法执行,导致Multiple请求同时进入线程块,最终形成死锁。当然,我们可以使用自定义线程池来扩展线程数,建立线程池拒绝机制来解决死锁问题。2.CyclicBarrier再看CyclicBarrier[?sa?kl?k][?b?ri?],也是一个复合词。其中,Cyclic是循环的意思,Barrier是栅栏的意思,译为栅栏。JDK注释中描述了它:一种允许一组线程全部等待彼此到达公共屏障点的同步辅助。循环屏障在涉及固定大小的线程方的程序中很有用,这些线程必须偶尔相互等待。屏障被称为循环屏障,因为它可以在等待线程被释放后重新使用。翻译一下总结为以下三点:CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到所有线程都到达一个共同的屏障点。使用CyclicBarrier在具有固定数量线程的程序中很有帮助,这些线程有时必须相互等待。屏障用循环装饰,因为屏障可以在所有线程相互释放后重新使用。从字面上理解,它的功能和CountdownLatch很相似,也是等待所有参与游戏的玩家都准备好后才开始。它是另一个多线程并发控制工具。与CountdownLatch不同,CyclicBarrier可以重复使用。在我们实际开发中,CyclicBarrier可以用于多线程计算数据,最终在应用场景中合并计算结果。比如需要计算N组人一年的平均工资。每个组需要多个线程并行计算。计算完一组后,开始下一组。这需要多轮并行计算。在这种场景下,CyclicBarrier比CountDownLatch更合适。3、两者的区别最后总结一下CountDownLatch和CyclicBarrier的区别,从以下四个方面来分析:CountDownLatch的计数器只能使用一次。可以使用reset()方法重置CyclicBarrier的计数器。CyclicBarrier可以处理更复杂的业务场景。例如,如果出现计算错误,可以结束阻塞,重新设置计数器,重新执行程序。CyclicBarrier提供了getNumberWaiting()方法来获取被CyclicBarrier阻塞的线程数。它还提供了isBroken()方法来判断被阻塞的线程是否被中断等,CountDownLatch会阻塞主线程,而CyclicBarrier不会阻塞主线程,只会阻塞子线程。好了,以上就是我对CountdownLatch和CycliBarriar的理解。
