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).在涉及一组固定大小的线程的程序 ...
随机推荐
- MAC下查看环境变量的值的方法
方法很简单,用到的命令是:echo. env : 查看所有的环境变量 方法:启动终端->输入 echo + 环境变量名, 回车,即可看到边聊的值. 例如:echo $JAVA_HOME
- 实现接口Controller定义控制器
实现接口Controller定义控制器 控制器提供访问应用程序的行为,通常通过服务接口定义或注解定义两种方法实现. 控制器解析用户的请求并将其转换为一个模型.在Spring MVC中一个控制器可以包含 ...
- 第29章 电容触摸屏—触摸画板—零死角玩转STM32-F429系列
第29章 电容触摸屏—触摸画板 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fir ...
- 中小学信息学奥林匹克竞赛-理论知识考点--ASCII
ASCII表说白了就是一张表. 表中记录着:字符 和 数字 的对应关系.比如:字符0对应的ASCII码是48,A对应的是65,a对应的是97. 只要记住这三个,其它的数字,大写,小写字母的ASCII码 ...
- Javascript与C#中使用正则表达式
JavaScript RegExp 对象 新建一个RegExp对象 new RegExp(pattern,[attributes]) 注: \d需要使用[0-9]来代替 参数 参数 ...
- iphone应用程序生命周期浅析
做iphone开发有必要知道iphone程序的生命周期,说白点就是当点击程序图标启动程序开始到退出程序整个使用运行过程中底下的代码都发生了什么,只有理解生命周期,有利于我们开发人员开发出更棒的应用 接 ...
- java基础 静态 static 问在多态中,子类静态方法覆盖父类静态方法时,父类引用调用的是哪个方法?
多态 package com.swift.jiekou; public class Jicheng_Tuotai_jingtai_diaoyong { public static void main( ...
- C编程经验总结4
{}体里的语句不管在一行还是在多行,之间都是要有: for与for之间可以是独立的,也可以是相互嵌套的 For( ; i<5; )=for( ;i<=4; ) 一般都是在循环里面进行判断 ...
- 【nginx】root alias 区别,以及server root , location root 区别
nginx-root-alias-详解 最近在研究前后端分离站点配置在同一域名下,发现root,alias有区别,而且所有的root如果都放置在location下面访问无效的问题,才有此总结,本文只是 ...
- [Luogu1341]无序字母对(欧拉回路)
按题意给定字符串建无向图,找欧拉回路 按照定义,当没有奇数度点或者只有2个奇数度点时才有欧拉回路 Code #include <cstdio> #include <algorithm ...