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() 示例

public class JoinThread {

    public static void main(String[] args) {
try {
Thread t1 = new MyThread("t1");// 新建线程t1
t1.start();// 启动线程
t1.join(); // 将线程t1加入到主线程main中,并且主线程main()会等待它的完成
System.out.println(Thread.currentThread().getName() + " main end.");
}catch(Exception e) {
e.printStackTrace();
}
}
static class MyThread extends Thread{
public MyThread(String name) {
super(name);
}
public void run() {
System.out.println(Thread.currentThread().getName() + " run start.");
for(int i = 0;i < 10000;i++)
;
System.out.println(Thread.currentThread().getName() + " run end.");
}
}
}
// 运行结果
t1 run start.
t1 run end.
main main end.

说明:

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

具体过程图解:

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

public final void join() throws InterruptedException {
join(0);
}
public final synchronized void join(long millis) throws InterruptedException {
  long base = System.currentTimeMillis();
  long now = 0;
  if (millis < 0) {
    throw new IllegalArgumentException("timeout value is negative");
  }   if (millis == 0) {
    while (isAlive()) {
      wait(0);
    }
  } else {
    while (isAlive()) {
      long delay = millis - now;
      if (delay <= 0) {
        break;
      }
      wait(delay);
      now = System.currentTimeMillis() - base;
    }
  }
}
public final synchronized void join(long millis, int nanos) throws InterruptedException {
  if (millis < 0) {
    throw new IllegalArgumentException("timeout value is negative");
  }
  if (nanos < 0 || nanos > 999999) { // 纳秒值范围在 (0 ~ 999999]
    throw new IllegalArgumentException("nanosecond timeout value out of range");
  }
  if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
    millis++;
  }
  join(millis);
}

上面源码是在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. Python的元类简单介绍

    * 类型 和类 在Python中,一切都是对象.类也是对象.所以一个类必须有一个类型 注意: 1.type Python3中所有的类都是通过type来创建出来的 2.object:Python3中所有 ...

  2. 用tarjan求LCA板子(比倍增快)

    懒!!直接转载!!!! https://solstice23.top/archives/62

  3. JAVASE(七)面向对象:封装性(特性之一)、构造器、属性、关键字

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一.封装性 1.为什么要使用封装性? 创建对象以后,可以通过对象.属性名的方法进行赋值.只能限制数据的类 ...

  4. Java实现 LeetCode 529 扫雷游戏(DFS)

    529. 扫雷游戏 让我们一起来玩扫雷游戏! 给定一个代表游戏板的二维字符矩阵. 'M' 代表一个未挖出的地雷,'E' 代表一个未挖出的空方块,'B' 代表没有相邻(上,下,左,右,和所有4个对角线) ...

  5. Java实现 LeetCode 58 最后一个单词的长度

    58. 最后一个单词的长度 给定一个仅包含大小写字母和空格 ' ' 的字符串 s,返回其最后一个单词的长度. 如果字符串从左向右滚动显示,那么最后一个单词就是最后出现的单词. 如果不存在最后一个单词, ...

  6. 第五届蓝桥杯JavaA组省赛真题

    解题代码部分来自网友,如果有不对的地方,欢迎各位大佬评论 题目1.猜年龄 题目描述 小明带两个妹妹参加元宵灯会.别人问她们多大了,她们调皮地说:"我们俩的年龄之积是年龄之和的6倍" ...

  7. java实现第六届蓝桥杯表格计算

    表格计算 某次无聊中, atm 发现了一个很老的程序.这个程序的功能类似于 Excel ,它对一个表格进行操作. 不妨设表格有 n 行,每行有 m 个格子. 每个格子的内容可以是一个正整数,也可以是一 ...

  8. 华为EMUI在service中不能打印debug级别的日志

    华为emui在service里面不能打印debug级别的日志,因为这个小问题调试了一上午,刚开始我还以为emui把系统service的启动流程都改了呢

  9. 架构C02-商业模式与架构设计

    商业模式与架构设计:A段架构与B段架构 <思考软件创新设计:A段架构师思考技术> A段架构师必须具备鲜活的创新思维,睿智的策略思考,犀利的洞察力和灵活的战术才能把握稍纵即逝的商机     ...

  10. Netty 源码解析: Netty 的 ChannelPipeline

    ChannelPipeline和Inbound.Outbound         我想很多读者应该或多或少都有 Netty 中 pipeline 的概念.前面我们说了,使用 Netty 的时候,我们通 ...