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).在涉及一组固定大小的线程的程序 ...
随机推荐
- Vue nodejs商城项目-搭建express框架环境
1.express-project 搭建express框架环境 安装express generator生成器 通过生成器自动创建项目 配置分析 安装 cnpm i -g express-generat ...
- 当Java遇见了Html--Servlet篇
###一.什么是servlet servlet是在服务器上运行的小程序.一个servlet就是一个 java类,并且通过"请求-响应"编程模型来访问的这个驻留在服务器内存里的程序. ...
- List<T>转换为二维数组
public <T> Object[][] toArrays(List<T> data){ Object[][] o=new Object[data.size()][20]; ...
- XCode快捷键使用
:first-child{margin-top:0!important}.markdown-body>:last-child{margin-bottom:0!important}.markdow ...
- BZOJ1046: [HAOI2007]上升序列(LIS)
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 5740 Solved: 2025[Submit][Status][Discuss] Descript ...
- 39条常见的Linux系统简单面试题
39条常见的Linux系统简单面试题 本文主要分享39条常见的Linux系统简单面试题,其中包括如何看当前Linux系统有几颗物理CPU和每颗CPU的核数.如何实时查看网卡流量为多少等等,希望对你有所 ...
- bootloader svc 模式
bootloader 和操作系统都是工作在svc模式下 /* * set the cpu to SVC32 mode */ mrs r0,cpsr bic r0,r0,#0x1f orr r0,r0, ...
- scrapy--Cookies
大家好,之前看到的关于cookies的应用,由于有段时间没看,再看的时候花了一些时间,来给大家总结下.本文是根据:"http://www.bubuko.com/infodetail-2233 ...
- PHP关闭notice级别的错误提示
1.在php.ini文件中改动error_reporting改为: error_reporting=E_ALL & ~E_NOTICE 2.如果你不能操作php.ini文件,你可以使用如下方法 ...
- Python学习笔记:logging(日志处理)
在一个软件中,日志是可以说必不可少的一个组成部分,通常会在定位客户问题或者记录软件使用情况等场景中会用到.logging模板块是Python的一个内置标准库,用于实现对日志的控制输出,对于平常的日志输 ...