在编写多线程的工作中,有个常见的问题:主线程(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. Frament 方法

    public final boolean isAdded() 如果该Fragment对象被添加到了它的Activity中,那么它返回true,否则返回false. public final boole ...

  2. .NET调用window串口读取电子秤的数据

    Private serialPort As SerialPort  '定义 Public Function CreateSerialPort() As String        Dim strWei ...

  3. ORACLE 學習筆記

    proc 里的 commit等于提交就是你做了insert或者update后,commit后才是真正修改或者插入了数据库中 如果不提交的话,那么这个表就被锁了 CURSOR MYCURSOR is   ...

  4. .Net中的Debug模式和Release模式

    1.Debug模式和Release模式 在vs中,运行程序有两种模式:Debug和Release 在bin目录下也会生成对应的文件夹,用于存放生成的dll等文件,这两种模式的区别如下: Debug:用 ...

  5. Hibernate映射之OneToOne(第二篇)

    这是在项目中实际遇到的一个问题,纠结了很久.一开始参考mkyong的 ,两边都写OneToOne ,后来查看了一下项目经理在原来一些模块中的写法. 学习一下: 首先是E-R图:  一个货品可以进行多次 ...

  6. 修改VNC分辨率大小

    实验系统是centos6.5,在被连接的机器上需要安装vncserver. 1.第一种方法:使用geometry参数进行调整使用man命令获得关于geometry参数的描述[root@secdb ~] ...

  7. 谈谈自己了解的spring.NET的依赖注入

         spring.net里实现了控制反转IOC(Inversion of control),也即依赖注入DI(Dependency Injection),以达到解耦的目的,实现模块的组件化.程序 ...

  8. C#函数式编程之惰性求值

    惰性求值 在开始介绍今天要讲的知识之前,我们想要理解严格求值策略和非严格求值策略之间的区别,这样我们才能够深有体会的明白为什么需要利用这个技术.首先需要说明的是C#语言小部分采用了非严格求值策略,大部 ...

  9. EF(Entity Framework)多对多关系下用LINQ实现"NOT IN"查询

    这是今天在实际开发中遇到的一个问题,需求是查询未分类的博文列表(未加入任何分类的博文),之前是通过存储过程实现的,今天用EF实现了,在这篇博文中记录一下. 博文的实体类BlogPost是这样定义的: ...

  10. Salesforce 快速查看被引入Package的组件

    在 Salesforce Package 生成一个新版本的时候,由于经常需要去检查有哪些新的组件将要被引入 Package 中,这个在有众多组件的情况下检查起来会有点眼花缭乱,为了方便,就想着用 JS ...