ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java多线程并发系列之闭锁(Latch)和栅栏(CyclicBarrier)

2019-07-27 09:51:44  阅读:281  来源: 互联网

标签:cyclicBarrier 多线程 CyclicBarrier await 线程 new Latch 椅子


JAVA并发包中有三个类用于同步一批线程的行为,分别是闭锁(Latch),信号灯(Semaphore)和栅栏(CyclicBarrier)。本贴主要说明闭锁(Latch)和栅栏(CyclicBarrier)。

1. 闭锁(Latch)

闭锁(Latch)  —— 确保多个线程在完成各自事务后,才会打开继续执行后面的内容,否则一直等待。

计数器闭锁(CountDownLatch) —— 是JDK5+ 里面闭锁的一个实现,允许一个或多个线程等待某个事件的发生。CountDownLatch  有个正数的计数器,countDown(); 对计数器做减法操作,await(); 等待计数器 = 0。所有await的线程都会阻塞,直到计数器为0或者等待线程中断或者超时。

 1 public static void main(String[] args) throws InterruptedException {
 2         // 申明,等待事件数量 5次
 3         CountDownLatch await = new CountDownLatch(5);
 4  
 5         // 依次创建并启动处于等待状态的5个MyRunnable线程
 6         for (int i = 1; i < 6; ++i) {
 7             new Thread(new MyRunnable(await, i)).start();
 8         }
 9  
10         System.out.println("等待线程开始工作......");
11         await.await();
12         System.out.println("结束!");
13 }
 1 public static class MyRunnable implements Runnable {
 2  
 3     private final CountDownLatch await;
 4     private final int num;
 5  
 6     public MyRunnable(CountDownLatch await, int num) {
 7         this.await = await;
 8         this.num  =  num;
 9     }
10  
11     public void run() {
12         try {
13             System.out.println("线程"+num+"执行完毕。");
14             await.countDown(); // 当前事件执行完毕,计数 -1
15         } catch (InterruptedException e) {
16             e.printStackTrace();
17         }
18     }
19 } 
运行结果:
等待线程开始工作......
线程1执行完毕。
线程2执行完毕。
线程3执行完毕。
线程4执行完毕。
线程5执行完毕。
结束!

 

流程如图所示:

 图1 - CountDownLatch 处理流程

 

2. 栅栏(CyclicBarrier)

栅栏类似于闭锁,它能阻塞一组线程直到某个事件发生。 栅栏与闭锁的关键区别在于,所有的线程必须同时到达栅栏位置,才能继续执行。闭锁用于等待事件,而栅栏用于等待其他线程。

场景: 比如甲乙丙三人一把椅子,甲做椅子腿,乙做椅子面,丙做椅子靠背。等3人都做成后,就可以组装成椅子了。这是一种并行迭代,将一个问题分成很多子问题,当一系列的子问题都解决之后(所有子问题线程都已经await(); ),此时将栅栏打开,所有子问题线程被释放,而栅栏位置可以留着下次使用。

 示例如下:

1 public static void main(String[] args) throws InterruptedException {
2     // 申明,等待线程数量 3次
3     CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
4 
5     // 依次创建并启动处于等待状态的3个MyRunnable2线程
6     new Thread(new ChairRunnable(cyclicBarrier, "椅子腿")).start();
7     new Thread(new ChairRunnable(cyclicBarrier, "椅子面")).start();
8     new Thread(new ChairRunnable(cyclicBarrier, "椅子背")).start();
9 }
 1 public static class ChairRunnable implements Runnable {
 2     private final CyclicBarrier cyclicBarrier;
 3     private final String event;
 4 
 5     public ChairRunnable(CyclicBarrier cyclicBarrier, String event) {
 6         this.cyclicBarrier = cyclicBarrier;
 7         this.event = event;
 8     }
 9 
10     public void run() {
11         try {
12             System.out.println("开始做【" + event + "】。");
13             Thread.sleep(new Random().nextInt(10000));
14             cyclicBarrier.await(); // 等待其他线程完成
15         } catch (InterruptedException e) {
16             e.printStackTrace();
17         } catch (BrokenBarrierException e) {
18             e.printStackTrace();
19         }
20         System.out.println("【" + event + "】做好了, 我们来一起组装吧!");
21     }
22 }
运行结果:
开始做【椅子腿】。
开始做【椅子背】。
开始做【椅子面】。
【椅子面】做好了, 我们来一起组装吧!
【椅子腿】做好了, 我们来一起组装吧!
【椅子背】做好了, 我们来一起组装吧!

 

流程如下图所示:

图2 - CyclicBarrier 处理流程

 

标签:cyclicBarrier,多线程,CyclicBarrier,await,线程,new,Latch,椅子
来源: https://www.cnblogs.com/steffen/p/11244715.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有