今天学习CountDownLatch这个类,作用感觉和join很像,然后就百度了一下,看了他们之间的区别。所以在此记录一下。

首先来看一下join,在当前线程中,如果调用某个thread的join方法,那么当前线程就会被阻塞,直到thread线程执行完毕,当前线程才能继续执行。join的原理是,不断的检查thread是否存活,如果存活,那么让当前线程一直wait,直到thread线程终止,线程的this.notifyAll 就会被调用。

我们来看一下这个应用场景:假设现在公司有三个员工A,B,C,他们要开会。但是A需要等B,C准备好之后再才能开始,B,C需要同时准备。我们先用join模拟上面的场景。

Employee.java:

public class Employee extends Thread{

	private String employeeName;

	private long time;

	public Employee(String employeeName,long time){
this.employeeName = employeeName;
this.time = time;
} @Override
public void run() {
try {
System.out.println(employeeName+ "开始准备");
Thread.sleep(time);
System.out.println(employeeName+" 准备完成");
} catch (Exception e) {
e.printStackTrace();
}
}
}

JoinTest.java:

public class JoinTest {

	public static void main(String[] args) throws InterruptedException {
Employee a = new Employee("A", 3000);
Employee b = new Employee("B", 3000);
Employee c = new Employee("C", 4000); b.start();
c.start(); b.join();
c.join();
System.out.println("B,C准备完成");
a.start();
}
}

最后输出结果如下:

C开始准备
B开始准备
B 准备完成
C 准备完成
B,C准备完成
A开始准备
A 准备完成

可以看到,A总是在B,C准备完成之后才开始执行的。

CountDownLatch中我们主要用到两个方法一个是await()方法,调用这个方法的线程会被阻塞,另外一个是countDown()方法,调用这个方法会使计数器减一,当计数器的值为0时,因调用await()方法被阻塞的线程会被唤醒,继续执行。

接下来,我们用CountDownLatch来模拟一下。

Employee.java:

public class Employee extends Thread{

	private String employeeName;

	private long time;

	private CountDownLatch countDownLatch;

	public Employee(String employeeName,long time, CountDownLatch countDownLatch){
this.employeeName = employeeName;
this.time = time;
this.countDownLatch = countDownLatch;
} @Override
public void run() {
try {
System.out.println(employeeName+ "开始准备");
Thread.sleep(time);
System.out.println(employeeName+" 准备完成");
countDownLatch.countDown();
} catch (Exception e) {
e.printStackTrace();
} }
}

CountDownLatchTest.java:

public class CountDownLatchTest {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(2);
Employee a = new Employee("A", 3000,countDownLatch);
Employee b = new Employee("B", 3000,countDownLatch);
Employee c = new Employee("C", 4000,countDownLatch); b.start();
c.start();
countDownLatch.await();
System.out.println("B,C准备完成");
a.start();
}
}

输出结果如下:

B开始准备
C开始准备
B 准备完成
C 准备完成
B,C准备完成
A开始准备
A 准备完成

上面可以看到,CountDownLatch与join都能够模拟上述的场景,那么他们有什么不同呢?这时候我们试想另外一个场景就能看到他们的区别了。

假设A,B,C的工作都分为两个阶段,A只需要等待B,C各自完成他们工作的第一个阶段就可以执行了。

我们来修改一下Employee类:

public class Employee extends Thread{

	private String employeeName;

	private long time;

	private CountDownLatch countDownLatch;

	public Employee(String employeeName,long time, CountDownLatch countDownLatch){
this.employeeName = employeeName;
this.time = time;
this.countDownLatch = countDownLatch;
} @Override
public void run() {
try {
System.out.println(employeeName+ " 第一阶段开始准备");
Thread.sleep(time);
System.out.println(employeeName+" 第一阶段准备完成"); countDownLatch.countDown(); System.out.println(employeeName+ " 第二阶段开始准备");
Thread.sleep(time);
System.out.println(employeeName+" 第二阶段准备完成"); } catch (Exception e) {
e.printStackTrace();
}
}
}

CountDownLatchTest类不需要做修改,输出结果入下:

B 第一阶段开始准备
C 第一阶段开始准备
B 第一阶段准备完成
B 第二阶段开始准备
C 第一阶段准备完成
C 第二阶段开始准备
B,C第一阶段准备完成
A 第一阶段开始准备
B 第二阶段准备完成
A 第一阶段准备完成
A 第二阶段开始准备
C 第二阶段准备完成
A 第二阶段准备完成

从结果可以看出,A在B,C第一阶段准备完成的时候就开始执行了,不需要等到第二阶段准备完成。这种场景下,用join是没法实现的。

总结:调用join方法需要等待thread执行完毕才能继续向下执行,而CountDownLatch只需要检查计数器的值为零就可以继续向下执行,相比之下,CountDownLatch更加灵活一些,可以实现一些更加复杂的业务场景。

参考:https://blog.csdn.net/zhutulang/article/details/48504487

CountDownLatch与thread-join()的区别的更多相关文章

  1. Thread.join(), CountDownLatch、CyclicBarrier和 Semaphore区别,联系及应用

    在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch,CyclicBarrier和Semaphore,今天我们就来学习一下这三个辅助类的用法, 由于 ...

  2. JAVA多线程之CountDownLatch与join的区别

    首先,我们来看一个应用场景1: 假设一条流水线上有三个工作者:worker0,worker1,worker2.有一个任务的完成需要他们三者协作完成,worker2可以开始这个任务的前提是worker0 ...

  3. CountDownLatch与join的区别和联系

    首先,我们来看一个应用场景1: 假设一条流水线上有三个工作者:worker0,worker1,worker2.有一个任务的完成需要他们三者协作完成,worker2可以开始这个任务的前提是worker0 ...

  4. 多线程进阶---Thread.join()/CountDownLatch.await() /CyclicBarrier.await()

    Thread.join() CountDownLatch.await() CyclicBarrier.await() 三者都是用来控制程序的"流动" 可以让程序"堵塞&q ...

  5. CyclicBarrier、CountDownLatch、Callable、FutureTask、thread.join() 、wait()、notify()、Condition

    CyclicBarrier使用: import java.util.Random; import java.util.concurrent.BrokenBarrierException; import ...

  6. c# 大白话告诉你Thread的Sleep和Join的区别

    我们的程序默认会有两个线程,一个是主线程,一个是负责垃圾回收的线程.如果代码不使用多线程,就只有主线程这一条干道.1.在主线程中调用Thread.Sleep(1000),表示主线程阻塞自己1秒.2.在 ...

  7. thread.join 从异步执行变成同步

    Java的线程模型为我们提供了更好的解决方案,这就是join方法.在前面已经讨论过,join的功能就是使用线程 从异步执行变成同步执行 当线程变成同步执行后,就和从普通的方法中得到返回数据没有什么区别 ...

  8. Thread.join()分析方法

    API: join public final void join() throws InterruptedException 等待该线程终止. 抛出: InterruptedException - 假 ...

  9. sleep、yield、wait、join的区别(阿里面试)

    1.  Thread.sleep(long) 和Thread.yield()都是Thread类的静态方法,在调用的时候都是Thread.sleep(long)/Thread.yield()的方式进行调 ...

  10. 颠覆我的Thread.join()

    学而时习之,不亦说乎!                              --<论语> 为什么说是颠覆? 1)任何对象都可以作为锁对象,锁对象的行为都是一样的吗?之前我一直认为锁对 ...

随机推荐

  1. Redis学习笔记01--主从数据库配置

    1.创建公共配置文件 所有配置文件添加到以下目录: /xxxx/redis-slave-master 创建公共的redis配置文件,直接使用redis的默认配置文件,修改以下配置项: bind 127 ...

  2. 很全的atom问题解决方案

    atom插件 http://blog.csdn.net/qq_30100043/article/details/53558381 atom社区 https://atom-china.org/

  3. express+mysqle

    var mysql=require('mysql'); var connection=mysql.createConnection({ host:'',//地址 port:'',//端口号 user: ...

  4. 使用Docker快速搭建Nginx+PHP-FPM环境

    下载nginx官方镜像和php-fpm镜像 docker pull nginx docker pull bitnami/php-fpm 使用php-fpm镜像开启php-fpm应用容器 docker ...

  5. 0x02 译文:Windows桌面应用Win32第一个程序

    本节课我们将用C++ 写一个最简单的Windows 程序. 目录: 创建一个窗口 窗口消息 编写窗口过程 绘制窗口 关闭窗口 管理应用程序状态 代码如下: #ifndef UNICODE #defin ...

  6. Django之ORM模型

    ORM介绍 对象关系映射(Object Relational Mapping,简称ORM)模式的作用是在关系型数据库与业务实体对象之间进行映射,这使得我们不需要再去和复杂的SQL语句打交道,只需要简单 ...

  7. 敏捷冲刺每日报告三(Java-Team)

    第三天报告(10.27  周五) 团队:Java-Team 成员: 章辉宇(284) 吴政楠(286) 陈阳(PM:288) 韩华颂(142) 胡志权(143) github地址:https://gi ...

  8. 20162328蔡文琛week06

    学号 2016-2017-2 <程序设计与数据结构>第X周学习总结 教材学习内容总结 继承是从已有类派生出一个新类的过程. 继承的目的之一之复用已有的软件. 继承呢在子类和父类见建立了is ...

  9. Ubuntu下安装gsoap

    昨天在ubuntu下进行安装gSOAP,费了很多时间,没成功,今天又来找了大量教程资料,终于一次成功,这里写下自己的安装步骤和方法,供大家参考. 首先下载gsoap,我下载的是gsoap-2.8.1. ...

  10. github上传时出现error: src refspec master does not match any解决办法

    github上传时出现error: src refspec master does not match any解决办法 这个问题,我之前也遇到过,这次又遇到了只是时间间隔比较长了,为了防止以后再遇到类 ...