在工作中,我们经常需要和多线程打交道,简单说明一个场景,在工厂流水线上有2条流水线,流水线同时开工生产零件,但是每个零件生产时间不一样,只有等到两个零件都生产完毕之后才能开始总组装。那我们很快想到join就能做到。例如子线程thread调用了join,那么在子线程thread还存活的时候,让当前线程wait,直到thread死亡,就会调用当前线程的notifyAll方法。

简单用一个小例子来说明一下,现在有两个工作线程,分别给一个随机的工作时间t,然后在线程中给这个随机的工作时间+1s得到时间T;等到两个工作线程执行完毕之后,我们再执行第三个线程,这两个时间T加起来就是第三个线程的工作时间。那看一下代码和执行结果。

public class JoinTest {public static void main(String[] args) {WorkThread work_one = new WorkThread("work one", new Random().nextInt(10));
        WorkThread work_two = new WorkThread("work two", new Random().nextInt(10));
        work_one.start();
        work_two.start();

        try {work_one.join();
            work_two.join();
        } catch (InterruptedException e) {e.printStackTrace();
        }System.out.println("准备工作做完,可以开始干正事");

        WorkThread work_mian = new WorkThread("work main", work_one.getWorkTime() + work_two.getWorkTime());
        work_mian.start();
    }private static class WorkThread extends Thread {private int WorkTime;
        private String WorkName;

        public int getWorkTime() {return WorkTime;
        }public WorkThread(String WorkName, int WorkTime) {this.WorkName = WorkName;
            this.WorkTime = WorkTime;
            System.out.println(WorkName + " initialize time = " + WorkTime);
        }@Override
        public void run() {try {System.out.println(WorkName + " start work...");
                WorkTime = WorkTime + 1;
                Thread.sleep(1000 * WorkTime);
                System.out.println(WorkName + " complete work WorkTime = " + WorkTime);
            } catch (InterruptedException e) {e.printStackTrace();
                System.out.println(WorkName + " error work...");
            }}}
}

执行结果:

work one initialize time = 3
work two initialize time = 4
work one start work...
work two start work...
work one complete work WorkTime = 4
work two complete work WorkTime = 5
准备工作做完,可以开始干正事
work main initialize time = 9
work main start work...

work main complete work WorkTime = 10

那在jdk1.5之后,我们引入了CountDownLatch,CountDownLatch的原理就是先初始化执行线程的个数,执行完我们的工作之后就手动减一,等到读取的个数为0的时候,就开始总的工作。我们也用同样的场景来写一份代码。

public class CountDownLatchTest {public static void main(String[] args) {CountDownLatch countDownLatch = new CountDownLatch(2);
        WorkThread work_one = new WorkThread("work one", new Random().nextInt(10), countDownLatch);
        WorkThread work_two = new WorkThread("work two", new Random().nextInt(10), countDownLatch);
        work_one.start();
        work_two.start();

        //等待结果
        try {countDownLatch.await();
            System.out.println("准备工作做完,可以开始干正事");
            WorkThread work_main = new WorkThread("work main", work_one.getWorkTime() + work_two.getWorkTime(), null);
            work_main.start();
        } catch (InterruptedException e) {e.printStackTrace();
        }}private static class WorkThread extends Thread {private int WorkTime;
        private String WorkName;
        private CountDownLatch countDownLatch;

        public int getWorkTime() {return WorkTime;
        }public WorkThread(String WorkName, int WorkTime, CountDownLatch countDownLatch) {this.WorkName = WorkName;
            this.WorkTime = WorkTime;
            this.countDownLatch = countDownLatch;
            System.out.println(WorkName + " initialize time = " + WorkTime);
        }@Override
        public void run() {try {System.out.println(WorkName + " start work...");
                WorkTime = WorkTime + 1;
                Thread.sleep(1000 * WorkTime);
                System.out.println(WorkName + " complete work WorkTime = " + WorkTime);
                //工作完成后减一
                if (countDownLatch != null) {countDownLatch.countDown();
                }} catch (InterruptedException e) {e.printStackTrace();
                System.out.println(WorkName + " error work...");
            }}}
}

附上执行结果:

work one initialize time = 7
work two initialize time = 8
work one start work...
work two start work...
work one complete work WorkTime = 8
work two complete work WorkTime = 9
准备工作做完,可以开始干正事
work main initialize time = 17
work main start work...

work main complete work WorkTime = 18

当然为什么要提供CountDownLatch呢,不是有join就够了吗。那我们看下第二个场景,这个是join做不到的。因为CountDownLatch带有计数器。比如有一个会议,每个人都要在会议上做笔记,那我们现在由于会议需要提前进行,只要人到了就开始会议,不需要花几分钟带上笔记本,会议之后再做笔记都行。这个时候CountDownLatch就能使用了。我们用代码看一下。

public class CountDownLatchTest {public static void main(String[] args) throws InterruptedException {CountDownLatch countDownLatch = new CountDownLatch(10);
        for (int i = 0; i < 10; i++) {new WorkThread(String.valueOf(i),new Random().nextInt(10),countDownLatch).start();
        }countDownLatch.await();
        System.out.println("会议开始,大家没有做笔记的可以会议之后做笔记了");
    }private static class WorkThread extends Thread {private int WorkTime;
        private String WorkName;
        private CountDownLatch countDownLatch;

        public int getWorkTime() {return WorkTime;
        }public WorkThread(String WorkName, int WorkTime, CountDownLatch countDownLatch) {this.WorkName = WorkName;
            this.WorkTime = WorkTime;
            this.countDownLatch = countDownLatch;
            System.out.println(WorkName + " initialize time = " + WorkTime);
        }@Override
        public void run() {try {System.out.println(WorkName + " start work...");
                WorkTime = WorkTime + 1;
                Thread.sleep(1000 * WorkTime);
                System.out.println(WorkName + " complete work step one WorkTime = " + WorkTime);
                //第一阶段 开会   完成后减一
                countDownLatch.countDown();
                //第二阶段   做笔记
                Thread.sleep(5000);
                System.out.println(WorkName + " complete work step two WorkTime = " + WorkTime);
            } catch (InterruptedException e) {e.printStackTrace();
                System.out.println(WorkName + " error work...");
            }}}
}

执行结果:

0 initialize time = 6
1 initialize time = 6
2 initialize time = 1
0 start work...
3 initialize time = 9
2 start work...
1 start work...
4 initialize time = 7
3 start work...
5 initialize time = 7
4 start work...
5 start work...
6 initialize time = 3
7 initialize time = 6
6 start work...
8 initialize time = 9
7 start work...
9 initialize time = 2
8 start work...
9 start work...
2 complete work step one WorkTime = 2
9 complete work step one WorkTime = 3
6 complete work step one WorkTime = 4
1 complete work step one WorkTime = 7
0 complete work step one WorkTime = 7
7 complete work step one WorkTime = 7
2 complete work step two WorkTime = 2
9 complete work step two WorkTime = 3
4 complete work step one WorkTime = 8
5 complete work step one WorkTime = 8
6 complete work step two WorkTime = 4
8 complete work step one WorkTime = 10
3 complete work step one WorkTime = 10
会议开始,大家没有做笔记的可以会议之后做笔记了
7 complete work step two WorkTime = 7
0 complete work step two WorkTime = 7
1 complete work step two WorkTime = 7
4 complete work step two WorkTime = 8
5 complete work step two WorkTime = 8
8 complete work step two WorkTime = 10

3 complete work step two WorkTime = 10

从结果可以看出有一部分是边开会边做笔记的,有一部分是会议结束之后做笔记的。这就是CountDownLatch独特的地方。

java多线程中CountDownLatch和join的使用相关推荐

  1. java多线程中的join方法详解

    java多线程中的join方法详解 方法Join是干啥用的? 简单回答,同步,如何同步? 怎么实现的? 下面将逐个回答. 自从接触Java多线程,一直对Join理解不了.JDK是这样说的:join p ...

  2. Java多线程中的ThreadLocal,可继承,可修改

    Java多线程中的ThreadLocal,可继承,可修改. package test;import java.util.Date;public class InheritableThreadLocal ...

  3. java并发中CountDownLatch的使用

    文章目录 主线程等待子线程全都结束之后再开始运行 等待所有线程都准备好再一起执行 停止CountdownLatch的await java并发中CountDownLatch的使用 在java并发中,控制 ...

  4. Java多线程中使用ReentrantLock、synchronized加锁 简单举例

    Java多线程中使用ReentrantLock.synchronized加锁 简单举例 public class Demo {final static Lock lock = new Reentran ...

  5. java多线程中的死锁、活锁、饥饿、无锁都是什么鬼?

    转载自 java多线程中的死锁.活锁.饥饿.无锁都是什么鬼? 死锁.活锁.饥饿是关于多线程是否活跃出现的运行阻塞障碍问题,如果线程出现了这三种情况,即线程不再活跃,不能再正常地执行下去了. 死锁 死锁 ...

  6. java 多线程的单例模式,Java多线程中的单例模式两种实现方式

    Java多线程中的单例模式 一.在多线程环境下创建单例 方式一: package com.ietree.multithread.sync; public class Singletion { priv ...

  7. java多线程同步与死锁_浅析Java多线程中的同步和死锁

    Value Engineering 1基于Java的多线程 多线程是实现并发机制的一种有效手段,它允许编程语言在程序中并发执行多个指令流,每个指令流都称为一个线程,彼此间相互独立,且与进程一样拥有独立 ...

  8. 多线程中Thread的join方法

    多线程中Thread的join方法 join简介 join方法是Thread类中的一个方法,该方法的定义是等待该线程执行直到终止.其实就说join方法将挂起调用线程的执行,直到被调用的对象完成它的执行 ...

  9. Java多线程中static变量的使用

    Java中 没处理好同步 导致两个线程同时为一个static变量赋值 会导致什么后果? Java中 没处理好同步 导致两个线程同时为一个static变量赋值 会导致什么后果?仅仅是多耗资源还是会引发异 ...

最新文章

  1. 智能零售来了!Amazon Go无人商店周一正式对公众开放
  2. Linux驱动程序中THIS_MODULE 的定义
  3. 《Android开发从零开始》——22.数据存储(1)
  4. selenium-webdriver for node 鼠标滑动到指定元素
  5. 不是计算机专业及其相关专业,对软件编程一窍不通,能学好编程吗?
  6. 关于Netbeans调试PHP
  7. BZOJ1419: Red is good
  8. c语言求一个数的位数不用循环_LeetCode基础算法题第181篇:将数字减少为零的步骤数...
  9. vs2013 使用vs调试器,发现调试器显示的数据错误。查看内存,发现内存是正确的。...
  10. 凸优化第九章无约束优化 9.3 梯度下降方法
  11. SAP 软件PS 模块系统操作之一工作分解结构(WBS)的创建
  12. 神舟计算机主板bios,神舟HASEE笔记本电脑开机进入BIOS的方法与bios设置图解
  13. GIF动画录制工具(写教程时用的比较小巧的gif工具)
  14. 决策树分类算法三种方式
  15. CSS属性前的 -webkit, -moz
  16. Ubuntu环境下用docker从0到1部署Elasticsearch 7集群
  17. PHP5 session 详解【经典】
  18. jupyter远程访问服务器
  19. 仿开心网的前端页面 html+css
  20. String的inturn()的运用

热门文章

  1. malloc申请内存问题
  2. could not retrieve mirrorlist报错解决方法
  3. 【企业微信】获取token 发送应用消息
  4. 小伙利用C++模仿酷狗7(Kugou7) UI界面源码,附带炫酷动画效果哦
  5. 前端 读取excel时间为数字的问题,日期格式转换
  6. 单反拍摄技巧:适当使用手动调焦
  7. Lucene倒排索引简述 细说倒排索引构建
  8. n!末尾有多少个0问题
  9. 进化计算-遗传算法之史上最直观交叉算子(动画演示)
  10. 我用这些方式赚钱了人生第一个100万