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).在涉及一组固定大小的线程的程序 ...
随机推荐
- redis 有序集合类型
- python-类对象以列表切片模式操作
#类对象以列表切片模式操作 class Person: def __init__(self): self.cache=[] def __setitem__(self, key, value): #修改 ...
- Multigrid for Poisson’s Equation
泊松方程如何用多重网格求解 来源:佐治亚理工学院 教授:Prof. Richard Vuduc 主页:http://vuduc.org/index.php 教授内容:http://vuduc.org/ ...
- 阅读detection
关于detecion的几篇文章,感觉有必要系统学习一下,并记录一下了,最近看书比较多,文章看得少,赶紧看看吧. FPN:Feature Pyramid Networks for Object Dete ...
- IOS开发中缓存策略
为了节约流量,同时也是为了更好的用户体验,目前很多应用都使用本地缓存机制,其中以网易新闻的缓存功能最为出色.我自己的应用也想加入本地缓存的功能,于是我从网上查阅了相关的资料,发现总体上说有两种方法.一 ...
- 利用python在windows环境下爬取赶集网工作信息。
主要用到了多进程和多线程的知识,最后结果保存成csv文件格式,如有需要可改成数据库版本. 对用到的库做下简要介绍,具体请参考官方文档: xpinyin.Pinyin:将输入的中文转成拼音 concur ...
- gdb-pada调试实例
先编写个简单的hello的程序 hello.c (ps:有没有头文件行不行,试试不就知道了) int main(){ printf("hello!\n"); int m,n; in ...
- vue学习--父子组件通讯
this.$parent // 子组件访问父组件 this.$root // 访问根实例 this.$children // 父组件的所有子元素 *一 ...
- React路由-进阶篇
路由进阶 1.多级路由,和之前的思想一样,在子路由里面继续写Route,继续挂载组件,就可以实现多级路由 比如这样:class Food extends Component{ render() { r ...
- @ApiModelProperty用法
@ApiModelProperty()用于方法,字段: 表示对model属性的说明或者数据操作更改 value–字段说明 name–重写属性名字 dataType–重写属性类型 required–是否 ...