线程的并发工具类之CountDownLatch和CyclicBarrier原理和使用(七) Dear 丶 2022-12-19 13:09 91阅读 0赞 今天分析 CountDownLatch和CyclicBarrier原理和使用: **1、CountDownLatch ** 闭锁 CountDownLatch 这个类能够使一个线程等待其他线程完成各自的工 作后再执行。例如,应用程序的主线程希望在负责启动框架服务的线程已经启动 所有的框架服务之后再执行。 CountDownLatch 是通过一个计数器来实现的,计数器的初始值为初始任务 的数量。每当完成了一个任务后,计数器的值就会减 1 (CountDownLatch.countDown() 方法)。当计数器值到达 0 时,它表示所有的已 经完成了任务,然后在闭锁上等待 CountDownLatch.await() 方法的线程就可以恢 复执行任务。 应用场景: 实现最大的并行性:有时我们想同时启动多个线程,实现最大程度的并行性。 例如,我们想测试一个单例类。如果我们创建一个初始计数为 1 的 CountDownLatch,并让所有线程都在这个锁上等待,那么我们可以很轻松地完成 测试。我们只需调用 一次 countDown() 方法就可以让所有的等待线程同时恢复执 行。开始执行前等待 n 个线程完成各自任务:例如应用程序启动类要确保在处理 用户请求前,所有 N 个外部系统已经启动和运行了,例如处理 excel 中多个表单。 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25hbmRhbzE1OA_size_16_color_FFFFFF_t_70][] 参见代码如 下 import java.util.concurrent.CountDownLatch; /** *类说明:演示CountDownLatch用法, * 共5个初始化子线程,6个闭锁扣除点,扣除完毕后,主线程和业务线程才能继续执行 */ public class UseCountDownLatch { static CountDownLatch latch = new CountDownLatch(6); /*初始化线程*/ private static class InitThread implements Runnable{ public void run() { System.out.println("Thread_"+Thread.currentThread().getId() +" ready init work......"); latch.countDown(); for(int i =0;i<2;i++) { System.out.println("Thread_"+Thread.currentThread().getId() +" ........continue do its work"); } } } /*业务线程等待latch的计数器为0完成*/ private static class BusiThread implements Runnable{ public void run() { try { latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } for(int i =0;i<3;i++) { System.out.println("BusiThread_"+Thread.currentThread().getId() +" do business-----"); } } } public static void main(String[] args) throws InterruptedException { new Thread(new Runnable() { public void run() { SleepTools.ms(1); System.out.println("Thread_"+Thread.currentThread().getId() +" ready init work step 1st......"); latch.countDown(); System.out.println("begin step 2nd......."); SleepTools.ms(1); System.out.println("Thread_"+Thread.currentThread().getId() +" ready init work step 2nd......"); latch.countDown(); } }).start(); new Thread(new BusiThread()).start(); for(int i=0;i<=3;i++){ Thread thread = new Thread(new InitThread()); thread.start(); } latch.await(); System.out.println("Main do ites work........"); } } 执行结果: ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25hbmRhbzE1OA_size_16_color_FFFFFF_t_70 1][] **2、CyclicBarrier** CyclicBarrier 的字面意思是可循环使用( Cyclic )的屏障( Barrier )。它要做 的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一 个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续运行。 CyclicBarrier 默认的构造方法是 CyclicBarrier ( int parties ),其参数表示屏障拦截 的线程数量,每个线程调用 await 方法告诉 CyclicBarrier 我已经到达了屏障,然 后当前线程被阻塞。 CyclicBarrier 还提供一个更高级的构造函数 CyclicBarrie (r int parties,Runnable barrierAction),用于在线程到达屏障时,优先执行 barrierAction ,方便处理更复 杂的业务场景。CyclicBarrier 可以用于多线程计算数据,最后合并计算结果的场景。 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25hbmRhbzE1OA_size_16_color_FFFFFF_t_70 2][] 参见代码如 下 import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CyclicBarrier; /** *类说明:演示CyclicBarrier用法,共4个子线程,他们全部完成工作后,交出自己结果, *再被统一释放去做自己的事情,而交出的结果被另外的线程拿来拼接字符串 */ public class UseCyclicBarrier { private static CyclicBarrier barrier = new CyclicBarrier(4,new CollectThread()); //存放子线程工作结果的容器 private static ConcurrentHashMap<String,Long> resultMap = new ConcurrentHashMap<>(); public static void main(String[] args) { for(int i=0;i<4;i++){ Thread thread = new Thread(new SubThread()); thread.start(); } } /*汇总的任务*/ private static class CollectThread implements Runnable{ @Override public void run() { StringBuilder result = new StringBuilder(); for(Map.Entry<String,Long> workResult:resultMap.entrySet()){ result.append("["+workResult.getValue()+"]"); } System.out.println(" the result = "+ result); System.out.println("do other business........"); } } /*相互等待的子线程*/ private static class SubThread implements Runnable{ @Override public void run() { long id = Thread.currentThread().getId(); resultMap.put(Thread.currentThread().getId()+"",id); try { Thread.sleep(1000+id); System.out.println("Thread_"+id+" ....do something "); barrier.await(); Thread.sleep(1000+id); System.out.println("Thread_"+id+" ....do its business "); barrier.await(); } catch (Exception e) { e.printStackTrace(); } } } } 结果: ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25hbmRhbzE1OA_size_16_color_FFFFFF_t_70 3][] **3、CountDownLatch** **和** **CyclicBarrier** **辨析** CountDownLatch 的计数器只能使用一次,而 CyclicBarrier 的计数器可以反复 使用。CountDownLatch.await 一般阻塞工作线程,所有的进行预备工作的线程执行countDown,而 CyclicBarrier 通过工作线程调用 await 从而自行阻塞,直到所有工 作线程达到指定屏障,再大家一起往下走。 在控制多个线程同时运行上,CountDownLatch 可以不限线程数量,而 CyclicBarrier 是固定线程数。 同时,CyclicBarrier 还可以提供一个 barrierAction ,合并多线程计算结果。 到此两种工具类分析完成。 [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25hbmRhbzE1OA_size_16_color_FFFFFF_t_70]: /images/20221120/003ad38ab1d942539faee6aa67d14616.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25hbmRhbzE1OA_size_16_color_FFFFFF_t_70 1]: /images/20221120/e769074b633b4739a6cbeac3cb5fc6f9.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25hbmRhbzE1OA_size_16_color_FFFFFF_t_70 2]: /images/20221120/d53a86e22bd14e89a1e89f2bfeb87dbb.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25hbmRhbzE1OA_size_16_color_FFFFFF_t_70 3]: /images/20221120/7b3bcf8bf8d1461b984796600d3b134c.png
相关 详解Java并发工具类:CountDownLatch和CyclicBarrier使用 在Java编程中,`CountDownLatch`和`CyclicBarrier`是两种常用的并发工具类,它们主要用于控制多个线程的执行顺序。 1. `CountDownLa 落日映苍穹つ/ 2024年10月25日 04:09/ 0 赞/ 7 阅读
相关 Java并发工具:CountDownLatch和CyclicBarrier使用示例 CountDownLatch和CyclicBarrier是Java中的两个重要并发工具,它们在控制多个线程的执行顺序上有各自的应用场景。以下是这两个工具的使用示例: 1. C 傷城~/ 2024年10月15日 22:12/ 0 赞/ 38 阅读
相关 Java并发工具:CountDownLatch和CyclicBarrier的使用误区 CountDownLatch和CyclicBarrier是Java中两种常用的并发控制工具。在使用过程中,可能会存在一些误区。以下是它们的常见误区: 1. **误解功能**: ゞ 浴缸里的玫瑰/ 2024年10月15日 12:03/ 0 赞/ 38 阅读
相关 Java并发工具:CountDownLatch和CyclicBarrier的使用示例 `CountDownLatch` 和 `CyclicBarrier` 都是 Java 中用于管理线程并发的工具类。以下是它们的基本使用示例: 1. **CountDownLa 柔情只为你懂/ 2024年10月10日 22:54/ 0 赞/ 48 阅读
相关 Java并发工具类:CountDownLatch和CyclicBarrier问题 CountDownLatch和CyclicBarrier是Java中常用的并发工具类,主要用于协调多个线程的执行顺序。下面分别解析这两个工具类可能遇到的问题。 1. Coun 旧城等待,/ 2024年09月16日 21:54/ 0 赞/ 66 阅读
相关 Java并发工具:CountDownLatch和CyclicBarrier使用案例 `CountDownLatch`和`CyclicBarrier`是Java中两个常用的并发工具,主要用于协调多个线程的执行。 1. CountDownLatch使用案例: 谁借莪1个温暖的怀抱¢/ 2024年09月10日 08:33/ 0 赞/ 69 阅读
相关 线程的并发工具类之CountDownLatch和CyclicBarrier原理和使用(七) 今天分析 CountDownLatch和CyclicBarrier原理和使用: 1、CountDownLatch 闭锁 CountDownLatch 这个类能够使一个线 Dear 丶/ 2022年12月19日 13:09/ 0 赞/ 92 阅读
相关 并发工具CountDownLatch和CyclicBarrier 1. 等待多线程完成的CountDownLatch CountDownLatch允许一个或多个线程等待其他线程完成操作。 背景: 在jdk1.5之前中的join方 ╰半橙微兮°/ 2022年11月20日 12:59/ 0 赞/ 217 阅读
相关 多线程之CountDownLatch和CyclicBarrier 一、倒计时CountDownLatch CountDownLatch是一个非常实用的多线程控制工具类,称之为“倒计时器”,它允许一个或多个线程一直等待,直到其他线程的操作 ╰+攻爆jí腚メ/ 2022年05月14日 00:20/ 0 赞/ 319 阅读
还没有评论,来说两句吧...