CountDownLatch与thread-join()的区别
今天学习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()的区别的更多相关文章
- Thread.join(), CountDownLatch、CyclicBarrier和 Semaphore区别,联系及应用
在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch,CyclicBarrier和Semaphore,今天我们就来学习一下这三个辅助类的用法, 由于 ...
- JAVA多线程之CountDownLatch与join的区别
首先,我们来看一个应用场景1: 假设一条流水线上有三个工作者:worker0,worker1,worker2.有一个任务的完成需要他们三者协作完成,worker2可以开始这个任务的前提是worker0 ...
- CountDownLatch与join的区别和联系
首先,我们来看一个应用场景1: 假设一条流水线上有三个工作者:worker0,worker1,worker2.有一个任务的完成需要他们三者协作完成,worker2可以开始这个任务的前提是worker0 ...
- 多线程进阶---Thread.join()/CountDownLatch.await() /CyclicBarrier.await()
Thread.join() CountDownLatch.await() CyclicBarrier.await() 三者都是用来控制程序的"流动" 可以让程序"堵塞&q ...
- CyclicBarrier、CountDownLatch、Callable、FutureTask、thread.join() 、wait()、notify()、Condition
CyclicBarrier使用: import java.util.Random; import java.util.concurrent.BrokenBarrierException; import ...
- c# 大白话告诉你Thread的Sleep和Join的区别
我们的程序默认会有两个线程,一个是主线程,一个是负责垃圾回收的线程.如果代码不使用多线程,就只有主线程这一条干道.1.在主线程中调用Thread.Sleep(1000),表示主线程阻塞自己1秒.2.在 ...
- thread.join 从异步执行变成同步
Java的线程模型为我们提供了更好的解决方案,这就是join方法.在前面已经讨论过,join的功能就是使用线程 从异步执行变成同步执行 当线程变成同步执行后,就和从普通的方法中得到返回数据没有什么区别 ...
- Thread.join()分析方法
API: join public final void join() throws InterruptedException 等待该线程终止. 抛出: InterruptedException - 假 ...
- sleep、yield、wait、join的区别(阿里面试)
1. Thread.sleep(long) 和Thread.yield()都是Thread类的静态方法,在调用的时候都是Thread.sleep(long)/Thread.yield()的方式进行调 ...
- 颠覆我的Thread.join()
学而时习之,不亦说乎! --<论语> 为什么说是颠覆? 1)任何对象都可以作为锁对象,锁对象的行为都是一样的吗?之前我一直认为锁对 ...
随机推荐
- Redis学习笔记01--主从数据库配置
1.创建公共配置文件 所有配置文件添加到以下目录: /xxxx/redis-slave-master 创建公共的redis配置文件,直接使用redis的默认配置文件,修改以下配置项: bind 127 ...
- 很全的atom问题解决方案
atom插件 http://blog.csdn.net/qq_30100043/article/details/53558381 atom社区 https://atom-china.org/
- express+mysqle
var mysql=require('mysql'); var connection=mysql.createConnection({ host:'',//地址 port:'',//端口号 user: ...
- 使用Docker快速搭建Nginx+PHP-FPM环境
下载nginx官方镜像和php-fpm镜像 docker pull nginx docker pull bitnami/php-fpm 使用php-fpm镜像开启php-fpm应用容器 docker ...
- 0x02 译文:Windows桌面应用Win32第一个程序
本节课我们将用C++ 写一个最简单的Windows 程序. 目录: 创建一个窗口 窗口消息 编写窗口过程 绘制窗口 关闭窗口 管理应用程序状态 代码如下: #ifndef UNICODE #defin ...
- Django之ORM模型
ORM介绍 对象关系映射(Object Relational Mapping,简称ORM)模式的作用是在关系型数据库与业务实体对象之间进行映射,这使得我们不需要再去和复杂的SQL语句打交道,只需要简单 ...
- 敏捷冲刺每日报告三(Java-Team)
第三天报告(10.27 周五) 团队:Java-Team 成员: 章辉宇(284) 吴政楠(286) 陈阳(PM:288) 韩华颂(142) 胡志权(143) github地址:https://gi ...
- 20162328蔡文琛week06
学号 2016-2017-2 <程序设计与数据结构>第X周学习总结 教材学习内容总结 继承是从已有类派生出一个新类的过程. 继承的目的之一之复用已有的软件. 继承呢在子类和父类见建立了is ...
- Ubuntu下安装gsoap
昨天在ubuntu下进行安装gSOAP,费了很多时间,没成功,今天又来找了大量教程资料,终于一次成功,这里写下自己的安装步骤和方法,供大家参考. 首先下载gsoap,我下载的是gsoap-2.8.1. ...
- github上传时出现error: src refspec master does not match any解决办法
github上传时出现error: src refspec master does not match any解决办法 这个问题,我之前也遇到过,这次又遇到了只是时间间隔比较长了,为了防止以后再遇到类 ...