当前位置: 首页 > 科技观察

简单了解CountDownLatch和CyclicBarrier的区别--高并发编程

时间:2023-03-18 02:02:40 科技观察

本文主要讨论高并发编程中两个非常有用的工具CyclicBarrier(同步屏障)和CountDownLatch(倒计时锁),两者都是java.util.concurrent并发packages中非常有用的并发工具类,为了帮助理解一些有趣的隐喻会结合起来,下面将对两者进行讨论。1.CountDownLatch倒计时锁(一个线程等待另外N个线程完成某事才可以执行)//创建一个倒计时锁,设置值为5finalCountDownLatch=newCountDownLatch(5);try{//启用5个线程for(inti=1;i<=5;i++){newThread(newRunnable(){@Overridepublicvoidrun(){try{Thread.sleep(1000);}catch(Exceptione){e.printStackTrace();}System.out.println("子线程执行!");//将latch锁中的值递减1latch.countDown();}}).start();}//处于阻塞状态,直到latch中的值为零之前执行后续操作latch.await();System.out.println("Mainthreadexecution");}catch(Exceptione){System.out.println("Catchexception");}}运行结果:分析:倒计时锁比较容易理解,这里结合实际场景辅助理解。场景:数据表中存储了大量数据,现在需要读取表中的所有信息。为了提高读取效率,在主线程中开启多个子线程共同读取数据表。接下来等待所有的子线程读完,然后将读到的内容进行汇总,在主线程中进行处理。首先设置一个CountDownLatch倒计时锁,设置倒计时值为5,每个子线程各干各的。工作完成后,执行latch.countDown()将倒计时锁的值减1,表示工作完成。主线程latch.await()之后的代码段一直处于等待状态,直到CountDownLatch的值为0才继续执行。2.可回收屏障CyclicBarrier(N个线程相互等待,所有线程必须等待任意一个线程完成)//创建一个屏障并设置一个值,当足够多的线程到达屏障时一起释放CyclicBarrierbarrier=newCyclicBarrier(5,()->{System.out.println("开始游戏");});ExecutorServiceexecutorPool=Executors.newCachedThreadPool();for(inti=1;i<=5;i++){intnum=i;Thread.sleep(1000);executorPool.execute(()->{try{System.out.println(num+"numberplayers,ready,waitingtoenterthegame");barrier.await();System.out.println(num+"numberplayer,alreadyenteredthegame");}catch(InterruptedExceptione){e.printStackTrace();}catch(BrokenBarrierExceptione){e.printStackTrace();}});}executorPool.shutdown();运行结果:分析:这里是一个帮助理解CyclicBarrier的例子。一开始创建一个CyclicBarrier对象,将parties的值设置为5(解释为开一个游戏房间,5个玩家都准备好后才能开始游戏,每个玩家都可以玩游戏)。循环开启多个线程,分别调用barrier.await()。据了解,球员们已经进入房间,做好了准备。当线程调用barrier.await()方法时,计数会加1,如果计数没有达到CyclicBarrier的预设值时,线程会进入等待状态。当threadbarrier.await()方法的计数达到CyclicBarrier预设的parties值时,游戏开始。此时所有线程(玩家)同时进入游戏。3、两者的比较最后,CyclicBarrier(同步屏障)和CountDownLatch(倒计时锁)都是不错的高并发编程工具。两者非常相似,容易引起混淆。通过了解它们各自的工作方式和特点,结合业务需求应用它们,将会有很好的收益。