线程通信——CountDownLatch和CyclicBarrier
来源:互联网 发布:dyndns免费域名申请 编辑:程序博客网 时间:2024/04/28 19:42
CountDownLatch和CyclicBarrier
CyclicBarrier和CountDownLatch都是java的线程通信工具类,他们的都是对常用的线程通信模型进行了封装,为了更方便让我们完成线程交互通信。那么这两个通信模型的如何工作,他们俩有什么区别呢。
CyclicBarrier
CyclicBarrier 定义
A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point. CyclicBarriers are useful in programs involving a fixed sized party of threads that must occasionally wait for each other.
主要就是说,CyclicBarrier可以模拟一堆线程相互等待,直到到达一个相同的界值(barrier point),然后一起继续执行。CyclicBarrier的主要作用是模拟线程间相互等待的一个过程。
这是网上找的一个例子,我非常喜欢这个例子
题:
4个玩家一起闯关,只有当4个玩家一起过关时,才能继续下一关
下面是代码
/** * 玩家 */public class CBPlayer implements Runnable { private CyclicBarrier cyclicBarrier; private int id; public CBPlayer(int id, CyclicBarrier cyclicBarrier) { this.cyclicBarrier = cyclicBarrier; this.id = id; } @Override public void run() { try { System.out.println("玩家" + id + "正在玩第一关..."); cyclicBarrier.await(); System.out.println("玩家" + id + "进入第二关..."); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } }}
Game启动
public class CBGameBarrier { public static void main(String[] args) { CyclicBarrier cyclicBarrier = null; cyclicBarrier = new CyclicBarrier(4, new Runnable() { @Override public void run() { System.out.println("所有玩家进入第二关!2秒后一起进入下一关..."); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } } }); for (int i = 0; i < 4; i++) { new Thread(new CBPlayer(i, cyclicBarrier)).start(); } }}
输出结果
玩家0正在玩第一关...玩家3正在玩第一关...玩家2正在玩第一关...玩家1正在玩第一关...所有玩家进入第二关!2秒后一起进入下一关...玩家0进入第二关...玩家2进入第二关...玩家1进入第二关...玩家3进入第二关...
可以看出4位玩家这里有个相互等待的一个过程,直到4个玩家一起通关后,显示“所有玩家进入第二关!2秒后一起进入下一关…”,这里因为在主线程做了sleep操作,4个玩家还被主线程卡了2秒后才一起进行下一关。
这个例子说明CyclicBarrier可以模拟出线程间相互等待的过程,并且在条件满足时,执行Runnable的run方法后,等待继续一起执行后续任务。
CountDownLatch
CountDownLatch 定义
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
大致就是说,允许一个或者多个线程进行等待,直到countDownlancher条件满足为止,这些线程继续工作。
老实说,我不觉得官方的这段话能让人很清晰的理解清楚这货的用法。
A {@code CountDownLatch} is initialized with a given count.The {@link #await await} methods block until the current count reaches
zero due to invocations of the {@link #countDown} method, after which
all waiting threads are released and any subsequent invocations of {@link #await await} return immediately. This is a one-shot phenomenon – the count cannot be reset. If you need a version that resets the count, consider using a {@link CyclicBarrier}.
这后面又说了countDownlancher是不能重置的,如果你想用重置操作,你可以用CyclicBarrier。
既然这样,那要你何用?不管怎么样,我们把上面的题目再实现一遍。
题:
4个玩家一起闯关,只有当4个玩家一起过关时,才能继续下一关
玩家
public class CDLPlayer implements Runnable { private CountDownLatch cdl; private int id; public CDLPlayer(int id, CountDownLatch cdl) { this.cdl = cdl; this.id = id; } @Override public void run() { try { System.out.println("玩家" + id + "正在玩第一关..."); cdl.countDown();//countDown计数+1 cdl.await(); System.out.println("玩家" + id + "进入第二关..."); } catch (InterruptedException e) { e.printStackTrace(); } }}
GAME 启动
public class CDLGameBarrier { public static void main(String[] args) { CountDownLatch cdl = new CountDownLatch(4); for (int i = 0; i < 4; i++) { new Thread(new CDLPlayer(i, cdl)).start(); } }}
输出
玩家1正在玩第一关...玩家2正在玩第一关...玩家3正在玩第一关...玩家0正在玩第一关...玩家0进入第二关...玩家1进入第二关...玩家2进入第二关...玩家3进入第二关...
这里可以发现,没有了中间等待2秒过关的过程,因为我细想了下,如果只用一个CountDownLatch,我不能实现这个功能。但是可以从例子中发现,调用await方法的线程会进行阻塞,调用countdown方法进行计数。CountDownLatch把计数和阻塞的方法分开了。这点区别还是很大的,也就是说,countdownlatch是更灵活的。
于是我想到了下面这个例子
题:
饺子工厂开工,要做600个饺子,有管理者、工人A、工人B、工人C 4个人,管理者负责监管工人的工作进度,每做完200个就向上汇报。
管理者\监工
/** * 监工 * */public class DumplingSupervisor extends Thread{ private CountDownLatch cdl; private int totalnum = 0; public DumplingSupervisor(){ cdl = new CountDownLatch(100); } public void report(){ synchronized (this) { cdl.countDown(); } } @Override public void run() { try { cdl.await(); } catch (InterruptedException e) { } totalnum = 100; System.out.println("管理者,100个饺子做完了"); synchronized (this) { cdl = new CountDownLatch(200 - totalnum); } totalnum = 200; try { cdl.await(); } catch (InterruptedException e) { } System.out.println("管理者,200个饺子做完了"); synchronized (this) { cdl = new CountDownLatch(400 - totalnum); } totalnum = 400; try { cdl.await(); } catch (InterruptedException e) { } System.out.println("管理者,400个饺子做完了"); synchronized (this) { cdl = new CountDownLatch(600 - totalnum); } totalnum = 600; try { cdl.await(); } catch (InterruptedException e) { } System.out.println("管理者,600个饺子做完了"); }}
包饺子的人\工人
/** * 包饺子的人 * */public class DumplingWork extends Thread { private DumplingSupervisor supervisor; private String name; private int rate;// 饺子/秒, 工作效率。如果是5,就是5个饺子每秒 public DumplingWork(String name, int rate, DumplingSupervisor supervisor) { this.supervisor = supervisor; this.name = name; this.rate = rate; } @Override public void run() { int count = 200; for (int i = 0; i < count; i++) { // 做了一个饺子 try { Thread.sleep(1000 / rate); } catch (InterruptedException e) { e.printStackTrace(); } supervisor.report();// 每做完一个向领导报告 } System.out.println(name + "报告,工作做完了"); }}
作坊
/** * 作坊 */public class DumplingWorkShop { public static void main(String[] args) { DumplingSupervisor supervisor = new DumplingSupervisor();//监管人 DumplingWork workA = new DumplingWork("A", 20, supervisor); DumplingWork workB = new DumplingWork("B", 30, supervisor); DumplingWork workC = new DumplingWork("C", 25, supervisor); supervisor.start(); workA.start(); workB.start(); workC.start(); }}
输出
管理者,100个饺子做完了管理者,200个饺子做完了管理者,400个饺子做完了B报告,工作做完了C报告,工作做完了管理者,600个饺子做完了A报告,工作做完了
因为A的工作效率最低,A是最后一个完成的,并且在A完成的同时,管理者报告600个饺子的项目完成了。
例子中,ABC工人的线程并没有线程等待,只是进行了单纯的计数任务(report),真正在线程等待的只有管理者。而管理者监控任务时,都去new了新的CountDownLatch
这个例子可以看出CountDownLatch和CyclicBarrier还是有很明显区别的。
总结
老实说,我这人不太会总结,我相信看完例子的同学肯定能了解他们的作用。
CyclicBarrier 可以模拟一堆线程相互等待,直到到达一个相同的界值,然后一起继续执行。
CountDownLatch 主要是用于出一个计数器,等待计数器到达指定目标时,使得等待线程继续执行。
- 线程通信——CountDownLatch和CyclicBarrier
- 线程执行顺序——CountDownLatch、CyclicBarrier 、join()、线程池
- 用CountDownLatch和CyclicBarrier处理并发线程
- Java线程学习笔记CountDownLatch 和CyclicBarrier
- java学习笔记.05——CyclicBarrier和CountDownLatch
- 多线程并发、同步,线程之间通信,主、子线程的一些问题(CountDownLatch、CyclicBarrier和Semaphore)
- Java CountDownLatch 和 CyclicBarrier
- CountDownLatch和CyclicBarrier介绍
- CyclicBarrier和CountDownLatch介绍
- CyclicBarrier和CountDownLatch区别
- CountDownLatch、CyclicBarrier和Semaphore
- CountDownLatch、CyclicBarrier和Semaphore
- CountDownLatch、CyclicBarrier和Semaphore
- CountDownLatch 和 CyclicBarrier
- CountDownLatch、CyclicBarrier和Semaphore
- CountDownLatch和CyclicBarrier介绍
- CountDownLatch、CyclicBarrier和Semaphore
- CountDownLatch 和 CyclicBarrier
- java 设计模式
- TypeError: 'numpy.float64' object cannot be interpreted as an index
- Enumeration
- hash,分离链接法,探测散列表(二次探测),再散列的代码
- 《spring-boot学习》-08-spring boot 优雅的使用mybatis
- 线程通信——CountDownLatch和CyclicBarrier
- 利用反射原理调用方法抛出异常:argument type mismatch
- JAVA面试题之基础篇
- tableView的一些使用
- P1192 台阶问题
- 浅谈php设计模式
- 高仿百度外卖地址添加功能(百度地图拖动定位,poi搜索,设置配送范围)
- 百度地图4.2.1DEMO生成APK时的报错解决方案
- Matlab Tricks(三十) —— 任意区间的均匀分布