CountDownLatch和CyclicBarrier 举例详解
有时候会有这样的需求,多个线程同时工作,然后其中几个可以随意并发执行,但有一个线程需要等其他线程工作结束后,才能开始。举个例子,开启多个线程分块下载一个大文件,每个线程只下载固定的一截,最后由另外一个线程来拼接所有的分段,那么这时候我们可以考虑使用CountDownLatch来控制并发。
CountDownLatch是JAVA提供在java.util.concurrent包下的一个辅助类,可以把它看成是一个计数器,其内部维护着一个count计数,只不过对这个计数器的操作都是原子操作,同时只能有一个线程去操作这个计数器,CountDownLatch通过构造函数传入一个初始计数值,调用者可以通过调用CounDownLatch对象的cutDown()方法,来使计数减1;如果调用对象上的await()方法,那么调用者就会一直阻塞在这里,直到别人通过cutDown方法,将计数减到0,才可以继续执行。
/**
* Created by DELL on 2017/1/4.
*/
import java.util.concurrent.CountDownLatch; public class Thread2 {
/**
* 计数器,用来控制线程
* 传入参数2,表示计数器计数为2
*/
private final static CountDownLatch mCountDownLatch = new CountDownLatch(2); /**
* 示例工作线程类
*/
private static class WorkingThread extends Thread {
private final String mThreadName;
private final int mSleepTime;
public WorkingThread(String name, int sleepTime) {
mThreadName = name;
mSleepTime = sleepTime;
} @Override
public void run() {
System.out.println("[" + mThreadName + "] started!");
try {
Thread.sleep(mSleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
mCountDownLatch.countDown();//减一
System.out.println("[" + mThreadName + "] end!");
}
} /**
* 示例线程类
*/
private static class SampleThread extends Thread { @Override
public void run() {
System.out.println("[SampleThread] started!");
try {
// 会阻塞在这里等待 mCountDownLatch 里的count变为0;
// 也就是等待另外的WorkingThread调用countDown()
mCountDownLatch.await();
} catch (InterruptedException e) { }
System.out.println("[SampleThread] end!");
}
} public static void main(String[] args) throws Exception {
// 最先run SampleThread
new SampleThread().start();
// 运行两个工作线程
// 工作线程1运行5秒
new WorkingThread("WorkingThread1", 5000).start();
// 工作线程2运行2秒
new WorkingThread("WorkingThread2", 2000).start();
}
}
执行结果如下:
[SampleThread] started! [WorkingThread2] started! [WorkingThread1] started! [WorkingThread2] end! [WorkingThread1] end! [SampleThread] end!
CyclicBarrier 例子如下:
import java.util.concurrent.CyclicBarrier; /**
* Created by DELL on 2017/1/4.
*/
public class thread3 {
public static final int INIT_NUM = 5; public static void main(String[] args) {
CyclicBarrier cyc = new CyclicBarrier(INIT_NUM, new Runnable() {
@Override
public void run() {
System.out.println("init cyclicBarrier----");
}
}); for (int i = 0; i < INIT_NUM; i++) {
new sampleCyclic(cyc).start();
}
} private static class sampleCyclic extends Thread {
CyclicBarrier barrier; public sampleCyclic(CyclicBarrier barrier) {
this.barrier = barrier;
} @Override
public void run() {
System.out.println("start=====");
try {
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("id" + Thread.currentThread().getId() + "working----");
}
} }
输出结果如下:
start=====
start=====
start=====
start=====
start=====
init cyclicBarrier----
id16working----
id13working----
id15working----
id14working----
id12working----
综上所述二者有甚区别呢?
| CountDownLatch | CyclicBarrier |
| 减计数方式 | 加计数方式 |
| 计算为0时释放所有等待的线程 | 计数达到指定值时释放所有等待线程 |
| 计数为0时,无法重置 | 计数达到指定值时,计数置为0重新开始 |
| 调用countDown()方法计数减一,调用await()方法只进行阻塞,对计数没任何影响 | 调用await()方法计数加1,若加1后的值不等于构造方法的值,则线程阻塞 |
| 不可重复利用 | 可重复利用 |
CountDownLatch : 一个线程(或者多个), 等待另外N个线程完成某个事情之后才能执行。CyclicBarrier : N个线程相互等待,任何一个线程完成之前,所有的线程都必须等待。
这样应该就清楚一点了,对于CountDownLatch来说,重点是那个“一个线程”, 是它在等待, 而另外那N的线程在把“某个事情”做完之后可以继续等待,可以终止。而对于CyclicBarrier来说,重点是那N个线程,他们之间任何一个没有完成,所有的线程都必须等待。
CountDownLatch 是计数器, 线程完成一个就记一个, 就像 报数一样, 只不过是递减的.
而CyclicBarrier更像一个水闸, 线程执行就想水流, 在水闸处都会堵住, 等到水满(线程到齐)了, 才开始泄流.
CountDownLatch和CyclicBarrier 举例详解的更多相关文章
- 举例详解Python中的split()函数的使用方法
这篇文章主要介绍了举例详解Python中的split()函数的使用方法,split()函数的使用是Python学习当中的基础知识,通常用于将字符串切片并转换为列表,需要的朋友可以参考下 函数:sp ...
- iOS 多线程之NSOperation篇举例详解
这篇博客是接着总篇iOS GCD NSOperation NSThread等多线程各种举例详解写的一个支篇.总篇也包含了此文的链接.本文讲解的知识点有NSBlockOperationClick,队列, ...
- ios 多线程之NSThread篇举例详解
这篇博客是接着总篇iOS GCD NSOperation NSThread等多线程各种举例详解写的一个支篇.总篇也包含了此文的链接.本文讲解的知识点有NSThread的开始.取消.在当前线程执行任务. ...
- CyclicBarrier 使用详解
原文:https://www.jianshu.com/p/333fd8faa56e 1. CyclicBarrier 是什么? 从字面上的意思可以知道,这个类的中文意思是“循环栅栏”.大概的意思就是一 ...
- 举例详解CSS中的cursor属性
这篇文章主要举例介绍了CSS中的cursor属性,包括zoom-in/zoom-out和grab/grabbing等常用属性值的使用,需要的朋友可以参考下 一.开篇之言 CSS3的领域范围已经渗透到了 ...
- JAVA CyclicBarrier类详解
一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point).在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时CyclicBarrie ...
- join和countDownLatch原理及区别详解
先上结论 原理 join 原理:在当前线程中调用另一个线程线程 thread 的 join() 方法时,会调用该 thread 的 wait() 方法,直到这个 thread 执行完毕(JVM在 ru ...
- java基础-泛型举例详解
泛型 泛型是JDK5.0增加的新特性,泛型的本质是参数化类型,即所操作的数据类型被指定为一个参数.这种类型参数可以在类.接口.和方法的创建中,分别被称为泛型类.泛型接口.泛型方法. 一.认识泛型 在没 ...
- iOS GCD NSOperation NSThread等多线程各种举例详解(拷贝)
2年多的iOS之路匆匆而过,期间也拜读来不少大神的博客,近来突然为自己一直做伸手党感到羞耻,是时候回馈社会.回想当年自己还是小白的时候,照着一些iOS多线程教程学,也只是照抄,只知其然.不知其所以然. ...
随机推荐
- Vue.js双向绑定的实现原理
Vue.js最核心的功能有两个,一是响应式的数据绑定系统,二是组件系统.本文仅探究几乎所有Vue的开篇介绍都会提到的hello world双向绑定是怎样实现的.先讲涉及的知识点,再参考源码,用尽可能少 ...
- js windows.open()模拟POST提交
function openPostWindow (url,name, data1, data2) { var tempForm = document.createE ...
- ansible 简单使用
前面讲完安装,现在说说怎么用 1.创建目录 mkdir -p /etc/ansible 2. 编辑(或创建)/etc/ansible/hosts 并在其中加入一个或多个远程系统:echo '192.1 ...
- (转)微信小程序破解IDE
1.IDE下载 微信web开发者工具,本人是用的windows 10 x64系统,用到以下两个版本的IDE安装工具与一个破解工具包: wechat_web_devtools_0.7.0_x64.exe ...
- solr添加安全设置
solr版本为5.2.1 配置在了外网,不希望任何人都能拿到数据,所以添加了安全设置,参考 http://www.jianshu.com/p/1e79edb2b817 按照上面的流程走了一遍 1./u ...
- How repair disk issue when "Fsck Failed please repair manually and reboot"
" Fsck Failed please repair manually and reboot. the root filesystem is currently mounted as re ...
- 随手记一次用C#正则表达式获取下拉菜单html标签<select>以及相关属性值
随手记一次用C#正则表达式获取下拉菜单html标签<select>以及相关属性值 1:有如下html: .................. <select id="aaa ...
- 项目 XXX 的 NuGet 程序包还原失败:找不到“xxx”版本的程序包“xxx”
项目 XXX 的 NuGet 程序包还原失败:找不到“xxx”版本的程序包“xxx” 编译新下载的代码出错 修改包管理器的源为 http://www.nuget.org/api/v2/ .重试后成功 ...
- 百度富文本编辑器UEDITOR
前言 http://jingyan.baidu.com/article/a948d65108d7fa0a2dcd2e8d.html 配置<a>测试啊</a>.net mvc4项 ...
- Java多线程代码示例
package algorithm; class Mythread extends Thread{ String name; public Mythread(String name){ this.na ...