CyclicBarrier和CountDownLatch的使用
CyclicBarrier:
api对CyclicBarrier的描述: 一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。 也就是说他可以使一组线程先等待 然后达到某个条件之后再一起执行,有点map/reduce的感觉。
举个例子: 目前有个int, 分配3个任务线程对他加1 , 最后主任务线程汇集计算结果,代码如下:
private static AtomicInteger i = new AtomicInteger(0);
public static void main(String[] args){
CyclicBarrier cb = new CyclicBarrier(3,new Runnable() {
//主任务汇集计算结果
public void run() {
System.out.println("结果为" + i.get());
}
});
ExecutorService es = Executors.newFixedThreadPool(5);
es.submit(new SubTask(cb, "线程一"));
es.submit(new SubTask(cb, "线程二"));
es.submit(new SubTask(cb, "线程三"));
es.shutdown();
} //子任务计算
private static class SubTask implements Runnable{
private CyclicBarrier cb;
private String msg;
public SubTask(CyclicBarrier cb, String msg){
this.cb = cb;
this.msg = msg;
}
public void run() {
try {
System.out.println(msg + " enter");
i.incrementAndGet();
Thread.sleep(1000l);
cb.await();
System.out.println(msg + " quit");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
结果:
线程一 enter
线程三 enter
线程二 enter
结果为3
线程三 quit
线程二 quit
线程一 quit
如果定义的参与者线程比实际的线程要少会怎么样? 比如上例中es提交4个任务结果会怎样?
api中描述:因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier 所以如果修改代码如下:
CyclicBarrier cb = new CyclicBarrier(3,new Runnable() {
//主任务汇集计算结果
public void run() {
System.out.println("结果为" + i.get());
}
});
ExecutorService es = Executors.newFixedThreadPool(5);
es.submit(new SubTask(cb, "线程一"));
es.submit(new SubTask(cb, "线程二"));
es.submit(new SubTask(cb, "线程三"));
es.submit(new SubTask(cb, "线程四"));
es.shutdown();
则结果是运行完先进入的三个线程之后 第四个线程一直堵塞。
可能的输出:
线程一 enter
线程三 enter
线程二 enter
线程四 enter
结果4
线程三 quit
线程四 quit
线程一 quit
如上结果所示 有一个线程一直堵塞中
CountDownLatch:
api对CountDownLatch描述:一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。用给定的计数 初始化 CountDownLatch。由于调用了 countDown() 方法,所以在当前计数到达零之前,await 方法会一直受阻塞。之后,会释放所有等待的线程,await 的所有后续调用都将立即返回。这种现象只出现一次——计数无法被重置。如果需要重置计数,请考虑使用 CyclicBarrier。
由此可见: CountDownLatch与CyclicBarrier的区别是: CyclicBarrier可以重复使用 而CountDownLatch不能重复使用
简单例子如下:
public static void main(String[] args) throws InterruptedException, BrokenBarrierException{
//分配3个子任务去完成
CountDownLatch cdl = new CountDownLatch(3);
Thread t = new Thread(new SubTask(cdl, "线程1"));
Thread t1 = new Thread(new SubTask(cdl, "线程2"));
Thread t2 = new Thread(new SubTask(cdl, "线程3"));
t.start();
t1.start();
t2.start();
//在3个子任务完成之前一直等待
cdl.await();
//3个子任务完成之后 主线程获取结果
System.out.print(i.get());
}
//子任务计算
private static class SubTask implements Runnable{
private CountDownLatch cb;
private String msg;
public SubTask(CountDownLatch cb, String msg){
this.cb = cb;
this.msg = msg;
}
public void run() {
i.incrementAndGet();
System.out.println(msg + "进入");
try {
Thread.sleep(1000l);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
cb.countDown();
}
}
结果:
线程2进入
线程1进入
线程3进入
3
还有一个与以上两个类使用方式非常相似的类: Semaphore
public int MAX = 10;
public Semaphore s = new Semaphore(MAX); public void semaphoreTest() throws InterruptedException{
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try{
s.acquire(MAX);
for(int i = 0; i<MAX; i++){
s.release();
Thread.sleep(1000L);
}
}catch(Exception e){
e.printStackTrace();
}
}
});
thread.start(); Thread.sleep(1000L); while(true){
try{
s.acquire();
System.out.print(1);
}catch(Exception e){
break;
}
}
}
这个类最大的作用个人感觉就是把许可数设置为1: new Semaphore(1) 然后充当一个互斥锁。这种方式与lock比较的优势在于: lock只能有持有他的线程来释放,而semaphore实现的互斥锁可由任何线程释放,对死锁恢复非常有帮助
CyclicBarrier和CountDownLatch的使用的更多相关文章
- CyclicBarrier和CountDownLatch的差别
CyclicBarrier和CountDownLatch都用多个线程之间的同步,共同点:同时有N个线程在 CyclicBarrier(CountDownLatch) 等待上等待时,CyclicBarr ...
- Java并发之CyclicBarrier、CountDownLatch、Phaser
在Java多线程编程中,经常会需要我们控制并发流程,等其他线程执行完毕,或者分阶段执行.Java在1.5的juc中引入了CountDownLatch和CyclicBarrier,1.7中又引入了Pha ...
- 《java.util.concurrent 包源码阅读》21 CyclicBarrier和CountDownLatch
CyclicBarrier是一个用于线程同步的辅助类,它允许一组线程等待彼此,直到所有线程都到达集合点,然后执行某个设定的任务. 现实中有个很好的例子来形容:几个人约定了某个地方集中,然后一起出发去旅 ...
- 使用数据库乐观锁解决高并发秒杀问题,以及如何模拟高并发的场景,CyclicBarrier和CountDownLatch类的用法
数据库:mysql 数据库的乐观锁:一般通过数据表加version来实现,相对于悲观锁的话,更能省数据库性能,废话不多说,直接看代码 第一步: 建立数据库表: CREATE TABLE `skill_ ...
- JAVA多线程提高十:同步工具CyclicBarrier与CountDownLatch
今天继续学习其它的同步工具:CyclicBarrier与CountDownLatch 一.CyclicBarrier CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公 ...
- java多线程开发之CyclicBarrier,CountDownLatch
最近研究了一个别人的源码,其中用到多个线程并行操作一个文件,并且在所有线程全部结束后才进行主线程后面的处理. 其用到java.util.concurrent.CyclicBarrier 这个类. Cy ...
- JDK源码分析之concurrent包(四) -- CyclicBarrier与CountDownLatch
上一篇我们主要通过ExecutorCompletionService与FutureTask类的源码,对Future模型体系的原理做了了解,本篇开始解读concurrent包中的工具类的源码.首先来看两 ...
- CyclicBarrier及CountDownLatch的使用
CountDownLatch位于java.util.concurrent包下,是JDK1.5的并发包下的新特性. 首先根据Oracle的官方文档看看CountDownLatch的定义: A synch ...
- Android进阶——多线程系列之Semaphore、CyclicBarrier、CountDownLatch
今天向大家介绍的是多线程开发中的一些辅助类,他们的作用无非就是帮助我们让多个线程按照我们想要的执行顺序来执行.如果我们按照文字来理解Semaphore.CyclicBarrier.CountDownL ...
- JAVA多线程学习十三 - 同步工具CyclicBarrier与CountDownLatch
一.CyclicBarrier CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point).在涉及一组固定大小的线程的程序 ...
随机推荐
- Python 爬虫的工具列表
这个列表包含与网页抓取和数据处理的Python库 网络 通用 urllib -网络库(stdlib). requests -网络库. grab - 网络库(基于pycurl). pycurl - 网络 ...
- Can Microsoft’s exFAT file system bridge the gap between OSes?
转自:http://arstechnica.com/information-technology/2013/06/review-is-microsofts-new-data-sharing-syste ...
- js中关于假值和空数组的总结
先上x==y运算符的算法细节: 如果x不是正常值(比如抛出一个错误),中断执行. 如果y不是正常值,中断执行. 如果Type(x)与Type(y)相同,执行严格相等运算x === y. 如果x是nul ...
- npm包发布过程
在上一章节中,我封装了一个基于react的树状组件,后来想把它发布到npm上,下面主要介绍一下发布过程中遇到的问题: 1.去注册npm账号,注册地址(https://www.npmjs.com), 再 ...
- machine learning学习笔记
看到Max Welling教授主页上有不少学习notes,收藏一下吧,其最近出版了一本书呢还,还没看过. http://www.ics.uci.edu/~welling/classnotes/clas ...
- BZOJ1901: Zju2112 Dynamic Rankings(整体二分 树状数组)
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 9094 Solved: 3808[Submit][Status][Discuss] Descript ...
- Eclipse+Python环境配置
Eclipse+Pydev 1.安装Eclipse Eclipse可以在它的官方网站Eclipse.org找到并下载,通常我们可以选择适合自己的Eclipse版本,比如Eclipse Classic. ...
- Servlet学习笔记03——什么是DAO?
1.案例 (1)添加用户 step1.建表 create table t_user( id int primary key auto_increment, username varchar(50) u ...
- 使用Jmeter性能测试,读取csv文件时的乱码问题
读取csv参数乱码问题 发送请求时参数通过CSV文件读取,发送请求后显示错误,把获取的参数通过在线urlencode转码器转码后发现是乱码.打开csv设值,编码格式选择的是UTF-8,打开参数文件后发 ...
- pyhton——logging日志模块的学习
https://www.cnblogs.com/yyds/p/6901864.html 本节内容 日志相关概念 logging模块简介 使用logging提供的模块级别的函数记录日志 logging模 ...