下载安卓APP箭头
箭头给我发消息

客服QQ:3315713922

编程语言如何区分CountDownLatch与CyclicBarrier

作者:课课家教育     来源: http://www.kokojia.com点击数:780发布时间: 2019-09-17 10:41:58

标签: 编程语言JavaJavascript

大神带你学编程,欢迎选课

简单地理解区分CountDownLatch与CyclicBarrier--高并发编程.J2ME(java2 Micro Edition,Java2平台的微型版),应用于移动、无线及有限资源的环境;J2SE(Java 2 Standard Edition,Java 2平台的标准版),应用于桌面环境;J2EE(Java 2Enterprise Edition,Java 2平台的企业版),应用于基于Java的应用服务器。Java 2平台的发布,是Java发展过程中最重要的一个里程碑,标志着Java的应用开始普及。

本文主要讨论在高并发编程中两非常实用工具CyclicBarrier(同步屏障)和CountDownLatch(倒计时锁),两者都是java.util.concurrent并发包内非常有用的并发工具类,为了帮助理解会结合一些有趣的比喻,下面将对两者进行讨论。

编程语言如何区分CountDownLatch与CyclicBarrier_编程语言_Java_Javascript_课课家

一、CountDownLatch倒计时锁(一个线程等待另外N个线程完成某个事情之后才能执行)

  1. //创建一个倒计时锁,设置值为5 
  2.  final CountDownLatch latch = new CountDownLatch(5); 
  3.  try { 
  4.  //启用5个线程 
  5.  for (int i = 1; i <= 5; i++) { 
  6.  new Thread(new Runnable() { 
  7.  @Override 
  8.  public void run() { 
  9.  try { 
  10.  Thread.sleep(1000); 
  11.  } catch (Exception e) { 
  12.  e.printStackTrace(); 
  13.  } 
  14.  System.out.println("子线程执行!"); 
  15.  //让latch锁中的数值减1 
  16.  latch.countDown(); 
  17.  } 
  18.  }).start(); 
  19.  } 
  20.  //处于阻塞状态直到latch中数值为零才执行后续操作 
  21.  latch.await(); 
  22.  System.out.println("主线程执行"); 
  23.  } catch (Exception e) { 
  24.  System.out.println("捕获异常"); 
  25.  } 

运行结果:

解析:倒计时锁理解起来比较容易,这里通过结合实际场景帮助理解。场景:一张数据表中存放大量的数据,现要读取表里的所有信息。为了提高读取效率便通过在主线程中开启多个子线程分工合作对数据表进行读取。接下来要等待全部子线程读取完毕之后,将读取到的内容进行汇总并在主线程中进行处理。

  • 首先先设置一个CountDownLatch倒计时锁 ,并设置倒计时值为5
  • 每一个子线程进行自己的工作,当工作执行完毕完毕后通过执行latch.countDown()对倒计时锁的值进行减1操作,表示自己工作完成。
  • 主线程latch.await() 后的代码段一直属于等待状态,直到CountDownLatch的值为0时才继续执行。

二、可循环使用的屏障CyclicBarrier(N个线程相互等待,任何一个线程完成之前,所有的线程都必须等待)

  1. //建立一个屏障并设定一个值,当有足够的线程达到屏障时再一起释放 
  2. CyclicBarrier barrier = new CyclicBarrier(5, () -> { 
  3. System.out.println("开始游戏"); 
  4. }); 
  5. ExecutorService executorPool = Executors.newCachedThreadPool(); 
  6. for (int i = 1; i <= 5; i++) { 
  7. int num = i
  8. Thread.sleep(1000); 
  9. executorPool.execute(() -> { 
  10. try { 
  11. System.out.println(num + "号玩家,已准备好,等待进入游戏"); 
  12. barrier.await(); 
  13. System.out.println(num + "号玩家,已经进入游戏"); 
  14. } catch (InterruptedException e) { 
  15. e.printStackTrace(); 
  16. } catch (BrokenBarrierException e) { 
  17. e.printStackTrace(); 
  18. }); 
  19. executorPool.shutdown(); 

运行结果:

解析:这里通过一个形象的例子来帮助理解CyclicBarrier。

  • 一开始建立一个CyclicBarrier对象并设置parties的值为5(理解为开启一个游戏房间,且需要5个玩家都准备好的条件之后才能开启游戏,各个玩家才能进行游戏游玩)。
  • 循环开启多个线程并各自调用barrier.await(),理解为玩家分别都进入房间并做好了准备,线程当调用barrier.await()方法计数会加1,如果计数还达不到CyclicBarrier预先设置的parties值时则该线程会进入等待状态。
  • 当线程barrier.await()方法计数达到CyclicBarrier预先设置的parties值时,便开始游戏。这个时候所有的线程(玩家)便同时进入到了游戏中。

三、两者对比

最后

CyclicBarrier(同步屏障)和CountDownLatch(倒计时锁)都是不错的高并发编程工具类,两者很相似容易造成混淆,通过理解两者各自工作方式和特点并结合业务需求合理地应用他们会有不错的效益。

由于C++所具有的优势,该项目组的研究人员首先考虑采用C++来编写程序。但对于硬件资源极其匮乏的单片式系统来说,c++程序过于复杂和庞大。另外由于消费电子产品所采用的嵌入式处理器芯片的种类繁杂,如何让编写的程序跨平台运行也是个难题。

赞(23)
踩(0)
分享到:
华为认证网络工程师 HCIE直播课视频教程