在编写多线程的工作中,有个常见的问题:主线程(main) 启动好几个子线程(task)来完成并发任务,主线程要等待所有的子线程完成之后才继续执行main的其它任务。

默认主线程退出时其它子线程不会停,如果想让main退出时其它子线程终止,可以用subThread.setDaemon(true) 设置子线程为“守护线程”。

如果要在主线程等待所有子线程完成后,还要执行其它操作(比如:结果合并).可以用join()方法来等待所有子线程完成后,才继续执行。如下:

实例1:Join实现

public class TestRunnable implements Runnable{

    /** 线程名 */
private String threadName; public TestRunnable(String threadName) {
this.threadName = threadName;
} @Override
public void run() {
System.out.println( "[" + threadName + "] Running !" );
} public static void main(String[] args) throws InterruptedException {
List<Thread> lists = new ArrayList<Thread>();
for(int i=0; i<5; i++){
Thread thread = new Thread(new TestRunnable("子线程" + (i + 100)));
lists.add(thread);
thread.start();
}
System.out.println("主线程阻塞,等待所有子线程执行完成");
for(Thread thread : lists){
// 如果注释掉thread.join(),启动后 main线程 与 所有子线程 thread并发工作,并不会等待子线程完成后再执行
thread.join();
}
System.out.println("所有线程执行完成!");
}
}

此外可以用java.util.concurrent.CountDownLatch类更简洁的实现这种场景.

CountDownLatch 的作用和 Thread.join() 方法类似,可用于一组线程和另外一组线程的协作。

例如:主线程在做一项工作之前需要一系列的准备工作,只有这些准备工作都完成,主线程才能继续它的工作,这些准备工作彼此独立,所以可以并发执行以提高速度。在这个场景下就可以使用 CountDownLatch 协调线程之间的调度了。

在直接创建线程的年代(Java 5.0 之前),我们可以使用 Thread.join().在 JUC 出现后,因为线程池中的线程不能直接被引用,所以就必须使用 CountDownLatch 了。

CountDownLatch 是能使一组线程等另一组线程都跑完了再继续跑 ,CountDownLatch.await() 方法在倒计数为0之前会阻塞当前线程.

实例2:CountDownLatch实现

public class TestRunnable implements Runnable{

    /** 处理main线程阻塞(等待所有子线程) */
private CountDownLatch countDown; /** 线程名字 */
private String threadName; public TestRunnable(CountDownLatch countDownLatch, String threadName) {
this.countDown = countDownLatch;
this.threadName = threadName;
} @Override
public void run() {
System.out.println( "[" + threadName + "] Running ! [countDownLatch.getCount() = " + countDown.getCount() + "]." );
// 每个独立子线程执行完后,countDownLatch值减1
countDown.countDown();
} public static void main(String [] args) throws InterruptedException {
int countNum = 5;
CountDownLatch countDownLatch = new CountDownLatch(countNum);
for(int i=0; i<countNum; i++){
new Thread(new TestRunnable(countDownLatch,"子线程" + (i+100))).start();
}
System.out.println("主线程阻塞,等待所有子线程执行完成");
//endLatch.await()使得主线程(main)阻塞直到endLatch.countDown()为零才继续执行
countDownLatch.await();
System.out.println("所有线程执行完成!");
}
}

执行结果:

对于countDownLatch我们需要注意:CountDownLatch.await() 方法在倒计数为0之前会阻塞当前线程.
a)在不适用await()的时候:

执行结果如下:

此时我们看到,主线程和子线程并发执行,主线程执行完后子线程还在执行,没有实现我们需要的场景.

b)CountDownLatch.await() 方法在倒计数不为0时

执行结果:

如图,可以看到,子线程执行完成了,但是countDownLatch的倒记数的值不为0,进入持续等待中,并没有唤醒主线程来执行.所以countDownLatch.await()生效必须保证计数值变为0.

转载请注明出处:[http://www.cnblogs.com/dennisit/p/4340611.html]

CountDownLatch线程阻塞用法实例的更多相关文章

  1. 详解Java多线程编程中LockSupport类的线程阻塞用法

    LockSupport类是Java6(JSR166-JUC)引入的一个类,提供了基本的线程同步原语.LockSupport实际上是调用了Unsafe类里的函数,归结到Unsafe里,只有两个函数: p ...

  2. 四种Java线程池用法解析

    本文为大家分析四种Java线程池用法,供大家参考,具体内容如下 http://www.jb51.net/article/81843.htm 1.new Thread的弊端 执行一个异步任务你还只是如下 ...

  3. 多线程之Java线程阻塞与唤醒

    线程的阻塞和唤醒在多线程并发过程中是一个关键点,当线程数量达到很大的数量级时,并发可能带来很多隐蔽的问题.如何正确暂停一个线程,暂停后又如何在一个要求的时间点恢复,这些都需要仔细考虑的细节.在Java ...

  4. C#线程池用法

    C#线程池用法 在C#编程语言中,使用线程池可以并行地处理工作,当强制线程和更新进度条时,会使用内建架构的ThreadPool类,为批处理使用多核结构,这里我们来看在C#编程语言中一些关于来自Syst ...

  5. AQS 框架之 LockSupport 线程阻塞工具类

    ■ 前言 并发包一直是 JDK 里面比较难理解的,同时也是很精美的语言,膜拜下 Doug Li 大神.作者不敢长篇大论,只求循序渐进地把并发包通过理论和实战 (代码) 的方式介绍给大家. 其实做每一件 ...

  6. Java多线程系列——线程阻塞工具类LockSupport

    简述 LockSupport 是一个非常方便实用的线程阻塞工具,它可以在线程内任意位置让线程阻塞. 和 Thread.suspend()相比,它弥补了由于 resume()在前发生,导致线程无法继续执 ...

  7. Java常见问题分析(内存溢出、内存泄露、线程阻塞等)

    Java垃圾回收机制(GC) 1.1 GC机制作用 1.2 堆内存3代分布(年轻代.老年代.持久代) 1.3 GC分类 1.4 GC过程 Java应用内存问题分析 2.1 Java内存划分 2.2 J ...

  8. Python回调函数用法实例

    Python回调函数用法实例 作者:no.body链接:https://www.zhihu.com/question/19801131/answer/27459821 什么是回调函数? 我们绕点远路来 ...

  9. CountDownLatch 线程工具类

    CountDownLatch:概念是,允许一个或多个线程等待其他线程完成操作: 在线程基础知识中,学习过线程的join方法,当前线程阻塞等待join线程执行完毕才能执行: 测试代码如下: public ...

随机推荐

  1. StringGrid 实例1:初始化StirngGrid的首行和首列

    实例1:初始化StirngGrid的首行和首列

  2. java中的内部类小结

    内部类不是很好理解,但说白了其实也就是一个类中还包含着另外一个类.如同一个人是由大脑.肢体.器官等身体结果组成,而内部类相当于其中的某个器官之一,例如心脏:它也有自己的属性和行为(血液.跳动).显然, ...

  3. 注意在<s:if test="#session.user.power==0">中不能用 <s:if test=$sessionScope.user.power==0">

    获取封装在session的对象 用#session.对象名,可以获取对象 用#session.对象名.属性,可以获取属性. 注意在<s:iftest="#session.user.po ...

  4. 用代码控制UI界面

           public class MainActivity extends Activity { //当第一次创建Activity时回调该方法 @Override protected void ...

  5. 省市区县镇级联数据JS版

    前言:网站开发经常会涉及到报名,报名通常就会有地区级联的要求.如下所示.做这个功能就必须要有数据支撑.昨天努力了一天,从网上鼓捣了一份数据.分享下.纯技术性分享,非盈利的.如果有侵权的地方请知会,马上 ...

  6. 简单利用jQuery加tomcat,让前端开发不再依赖于后端的接口

    前端开发的过程中,我们免不了和后端进行联调,这时候就会出现以下的尴尬场景: 接口没写好,没法做接下来的功能 功能写好了,接口没写好,没法测这个功能 联调了,除了BUG,不知道锅在谁身上,只得陪后端耗时 ...

  7. 大熊君说说JS与设计模式之------策略模式Strategy

    一,总体概要 1,笔者浅谈 策略模式,又叫算法簇模式,就是定义了不同的算法,并且之间可以互相替换,此模式让算法的变化独立于使用算法的客户. 策略模式和工厂模式有一定的类似,策略模式相对简单容易理解,并 ...

  8. JS代码风格指南

    一.基本格式 缩进 建议每级4个空格,可以给编辑器设置tab = 4个空格,自动转换 分号 不要省略分号,防止ASI(自动插入分号)错误 行宽 每行代码不超过80个字符,过长应该用操作符手动断行 断行 ...

  9. TPL实现Task.WhileAll扩展方法

    文章翻译整理自 Nikola Malovic 两篇博文: Task.WhileAll Awaitable task progress reporting 当 Task.WhenAll 遇见 Task. ...

  10. 模仿angularjs写了一个简单的HTML模版和js数据填充的示例

    <!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...