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)任何对象都可以作为锁对象,锁对象的行为都是一样的吗?之前我一直认为锁对 ...
随机推荐
- Eclipse安卓开发环境搭建
前提,Java SDK和Eclipse搭建完毕 下载android SDK并安装 (官网:http://sdk.android-studio.org/ ) 找到安装目录,运行“SDK Manager. ...
- java实现循环链表的增删功能
java实现循环链表的增删功能,完整代码 package songyan.test.demo; public class Demo { // java 实现循环链表 public static voi ...
- python之Redis的字符串类型操作
redis的数据类型: 字符串型 哈希 列表 集合 有序集合 1.String(字符串类型) set 命令: 设置一个键和值,键存在则只覆盖,返回ok > s ...
- Redis 中的数据类型及基本操作
Redis 内置的数据类型有 5种:字符串String.哈希Hash.列表List.集合Set.有序集合ZSet 字符串类型 String 是 Redis 中最基本的类型,一个 key 对应着一个 v ...
- HTTP协议----URI,URL,持久连接,管道与Cookie
URI与URL有什么不同呢? URI:Universal Resource Identifier统一资源标志符 URL:Universal Resource Locator统一资源定位器 URI是用来 ...
- JavaWeb学习笔记五 会话技术Cookie&Session
什么是会话技术? 例如网站的购物系统,用户将购买的商品信息存储到哪里?因为Http协议是无状态的,也就是说每个客户访问服务器端资源时,服务器并不知道该客户端是谁,所以需要会话技术识别客户端的状态.会话 ...
- HIVE使用mysql作为外置数据库配置详情
Hive安装配置(mysql) 安装mysql hadoop$:sudo apt-get update hadoop$:sudo apt-get install mysql-server 启动mysq ...
- 网络1711-1712班 c 语言评分总表一览
学号 姓名 作业地址 PTA实验作业5分 PTA排名2分 阅读代码2分 总结1分 代码规范扣分-2--0 总分 是否推荐博客 1 **莹 http://www.cnblogs.com/wwwwxy12 ...
- win10 安装mingw ruby rails
原文可以参考 https://ruby-china.org/topics/17581 在window10 安装ruby rails https://rubyinstaller.org/download ...
- 从源码角度看LinkedList一些基本操作(jdk1.7)
介绍 LinkedList是一个双向链表,就像下图展示那样,每个节点有个指向上个元素和一个指向下个元素的指针. 接下来我会对我们经常使用的方法进行介绍,代码如下 @Test public void t ...