Java 多线程基础(九)join 方法

一、join() 方法介绍

join() 定义 Thread 类中的,作用是:把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。如:线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。

Thread 类中分别定义了: join() 、join(long millis) 和 join(long millis, int nanos) 三个方法。

①、join():等待线程t执行完毕。

②、join(long millis):等待 t 线程,等待时间是 millis 毫秒。

③、join(long millis, int nanos) :等待 t 线程,等待时间是 millis 毫秒 + nanos 纳秒。

二、join() 示例

  1. public class JoinThread {
  2.  
  3. public static void main(String[] args) {
  4. try {
  5. Thread t1 = new MyThread("t1");// 新建线程t1
  6. t1.start();// 启动线程
  7. t1.join(); // 将线程t1加入到主线程main中,并且主线程main()会等待它的完成
  8. System.out.println(Thread.currentThread().getName() + " main end.");
  9. }catch(Exception e) {
  10. e.printStackTrace();
  11. }
  12. }
  13. static class MyThread extends Thread{
  14. public MyThread(String name) {
  15. super(name);
  16. }
  17. public void run() {
  18. System.out.println(Thread.currentThread().getName() + " run start.");
  19. for(int i = 0;i < 10000;i++)
  20. ;
  21. System.out.println(Thread.currentThread().getName() + " run end.");
  22. }
  23. }
  24. }
  1. // 运行结果
  2. t1 run start.
  3. t1 run end.
  4. main main end.

说明:

①、在“主线程main”中通过 new MyThread("t1") 新建“线程t1”。 接着,通过 t1.start() 启动“线程t1”,并执行t1.join()。
②、执行t1.join()之后,“主线程main”会进入“阻塞状态”等待t1运行结束。“子线程t1”结束之后,会唤醒“主线程main”,“主线程”重新获取cpu执行权,继续运行。

具体过程图解:

三、join() 解析(基于JDK 1.8)

  1. public final void join() throws InterruptedException {
  2. join(0);
  3. }
  4. public final synchronized void join(long millis) throws InterruptedException {
  5.   long base = System.currentTimeMillis();
  6.   long now = 0;
  7.   if (millis < 0) {
  8.     throw new IllegalArgumentException("timeout value is negative");
  9.   }
  10.  
  11.   if (millis == 0) {
  12.     while (isAlive()) {
  13.       wait(0);
  14.     }
  15.   } else {
  16.     while (isAlive()) {
  17.       long delay = millis - now;
  18.       if (delay <= 0) {
  19.         break;
  20.       }
  21.       wait(delay);
  22.       now = System.currentTimeMillis() - base;
  23.     }
  24.   }
  25. }
  26. public final synchronized void join(long millis, int nanos) throws InterruptedException {
  27.   if (millis < 0) {
  28.     throw new IllegalArgumentException("timeout value is negative");
  29.   }
  30.   if (nanos < 0 || nanos > 999999) { // 纳秒值范围在 (0 ~ 999999]
  31.     throw new IllegalArgumentException("nanosecond timeout value out of range");
  32.   }
  33.   if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
  34.     millis++;
  35.   }
  36.   join(millis);
  37. }

上面源码是在Thread 类中定义的: join() 、join(long millis) 和 join(long millis, int nanos) 三个方法。

从上面代码中可以看到,最主要的是 join(long millis) 方法,从该方法中可以发现:当传递的 millis  == 0 时,会进入while(isAlive())循环;即只要子线程是活的,主线程就不停的等待。

问题
虽然t1.join() 被调用的地方是发生在“main主线程”中,但是 t1.join() 是通过“子线程t1”去调用的 join()。那么,join() 方法中的 isAlive() 应该是判断“子线程t1”是不是 Alive 状态;对应的 wait(0) 也应该是“让子线程t1”等待才对。但如果是这样的话,t1.join() 的作用怎么可能是“让主线程等待,直到子线程s完成为止”呢,应该是让"子线程等待才对(因为调用子线程对象 t1 的 wait 方法嘛)"?
答案

wait() 的作用是让“当前线程”等待,而这里的“当前线程”是指当前在CPU上运行的线程。所以,虽然是调用子线程的 wait() 方法,但是它是通过“主线程”去调用的;所以,休眠的是主线程,而不是“子线程”!

Java 多线程基础(九)join() 方法的更多相关文章

  1. Java多线程中的join()方法

    一.join()方法介绍 join() 定义在Thread.java中.join()方法把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程.比如在线程B中调用了线程A的join( ...

  2. 浅谈Java多线程中的join方法

    先上代码 新建一个Thread,代码如下: package com.thread.test; public class MyThread extends Thread { private String ...

  3. Java多线程中的join方法

    新建一个Thread,代码如下: package com.thread.test; public class MyThread extends Thread { private String name ...

  4. java多线程中关于join方法的使用

    Thread的非静态方法join()让一个线程B"加入"到另外一个线程A的尾部.在A执行完毕之前,B不能工作.例如:         Thread t = new MyThread ...

  5. Java多线程10:join()方法

    一.前言 通过一个简单的例子引入join()方法 public class Thread01 extends Thread{ @Override public void run() { for(int ...

  6. 多线程基础知识---join方法

    join方法的作用 thread.join()方法用于把指定的线程加入到当前线程中,把当前线程的CPU执行时间让给另一个线程.比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继 ...

  7. Java并发编程--多线程中的join方法详解

    Java Thread中, join()方法主要是让调用该方法的thread在完成run方法里面的部分后, 再执行join()方法后面的代码 例如:定义一个People类,run方法是输出姓名年龄. ...

  8. [转]Java多线程干货系列—(一)Java多线程基础

    Java多线程干货系列—(一)Java多线程基础 字数7618 阅读1875 评论21 喜欢86 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们 ...

  9. Java 多线程——基础知识

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

随机推荐

  1. 使用websocket开发智能聊天机器人

    前面我们学习了异步web框架(sanic)和http异步调用库httpx,今天我们学习websocket技术. websocket简介 我们知道HTTP协议是:请求->响应,如果没有响应就一直等 ...

  2. Linux部分场景非常有用的命令集1_chattr&ldd&xargs&screen&ssh&磁盘&du

    这里不做详细说明或截图,仅作为记录和简单说明.注:可能只针对某一命令部分功能,不包含整个功能,若要查看全部请自行查阅文档或help 1.chattr 当某一文件或目录,不想被无意修改或删除(即使roo ...

  3. Redis详解(十)------ 从零开始搭建集群

    在上一篇博客我们介绍了------Redis哨兵(Sentinel)模式,哨兵模式主要是解决高可用问题,在master节点宕机时,slave节点能够自动切换成为master节点 本篇博客我们来介绍Re ...

  4. 【转】B树、B+树、B*树、R 树、QuadTree

    从B树.B+树.B*树谈到R 树 QuadTree(四叉树) 四叉树空间索引原理及其实现

  5. JBoss 5.x/6.x 反序列化漏洞(CVE-2017-12149)复现

    0x00 漏洞介绍 该漏洞为 Java反序列化错误类型,存在于 Jboss 的 HttpInvoker 组件中的 ReadOnlyAccessFilter 过滤器中.该过滤器在没有进行任何安全检查的情 ...

  6. Unity 游戏框架搭建 2019 (五十二~五十四) 什么是库?&第四章总结&第五章简介

    在上一篇,我们对框架和架构进行了一点探讨.我们在这一篇再接着探讨. 什么是库呢? 来自同一位大神的解释: 库, 插到 既有 架构 中, 补充 特定 功能. 很形象,库就是搞这个的.我们的库最初存在的目 ...

  7. Java实现 LeetCode 144 二叉树的前序遍历

    144. 二叉树的前序遍历 给定一个二叉树,返回它的 前序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,2,3] /** * Definition for a ...

  8. (二)CRLF注入

    01 漏洞描述 在<HTTP | HTTP报文>一文中,我们介绍了HTTP报文的结构:状态行和首部中的每行以CRLF结束,首部与主体之间由一空行分隔.或者理解为首部最后一个字段有两个CRL ...

  9. Swagger使用的时候报错:Failed to load API definition

    NuGet添加Swashbuckle.AspNetCore,在Startup.cs添加和启用中间件Swagger public void ConfigureServices(IServiceColle ...

  10. Centos7.x RPM安装ELK 7.5.0

    一.环境介绍   单位需要分析tomcat 日志和业务日志,比较以后还是选择用ELK 来进行日志的分析,以及可视化的展示. 系统环境 服务器: 1.AWS EC2 2C8G [root@ip-10-0 ...