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. 谁说双非本科就一定无缘阿里?H哥粉丝6面通过,喜提Offer!

    本文来自作者投稿(原作者:小胖儿),原作者是一位2021届本科毕业生,就读于一所双非(非985.非211)院校,在今年2月份的时候,我曾经帮他指导过简历,并且根据他的简历内容帮他提了一些可能会问到的问 ...

  2. 抛开 Spring ,你知道 MyBatis 加载 Mapper 的底层原理吗?

    原文链接:抛开 Spring ,你知道 MyBatis 加载 Mapper 的底层原理吗? 大家都知道,利用 Spring 整合 MyBatis,我们可以直接利用 @MapperScan 注解或者 @ ...

  3. [PHP学习教程 - 数字]001.数字补0(Num padding)

    引言:在日常工作中,经常要用到数字前后补0的操作,如:日期格式yyyy-MM-dd等等. 在php中有多种前后填充函数——今天,我们就介绍常用的两种,实现数字补零: str_pad sprintf 大 ...

  4. win服务器管理软件巧利用——如何让服务器管理事半功倍

    那些服务器管理大牛估计看到这个标题会笑了,服务器怎么管理,靠自带的远程桌面肯定是远远不够的,要实现上千台服务器同时登陆,没有一个好程序管理,估计得三餐不食为其颠倒. 那么,有什么好的服务器推荐呢?站长 ...

  5. Rocket - tilelink - first

    https://mp.weixin.qq.com/s/0nzkV4K1osNEQzrtITYxmw   介绍Edges中first/last/done的实现.   ​​   1. firstlastH ...

  6. js 识别二维码

    本文引用analyticCode.js.llqrcode.js实现识别二维码功能 html代码: <div class="box" id="analytic&quo ...

  7. 微信小程序单选按钮radio选中的值value的获取方法,setTimeout定时器的用法

    获取radio值的方法: func:function(e){ var val=e.detail.value;//获取radio值,类型:字符串 var val2=parseInt(val);//将字符 ...

  8. Java实现 LeetCode 768 最多能完成排序的块 II(左右便利)

    768. 最多能完成排序的块 II 这个问题和"最多能完成排序的块"相似,但给定数组中的元素可以重复,输入数组最大长度为2000,其中的元素最大为10**8. arr是一个可能包含 ...

  9. Java实现蓝桥杯突击战

    突击战 你有n个部下,每个部下需要完成一项任务.第i个部下需要你花Bi分钟交待任务,然后他会立刻独立地. 无间断地执行Ji分钟后完成任务.你需要选择交待任务的顺序, 使得所有任务尽早执行完毕(即最后一 ...

  10. C++实现网络寻路

    标题:网络寻路 X 国的一个网络使用若干条线路连接若干个节点.节点间的通信是双向的.某重要数据包,为了安全起见,必须恰好被转发两次到达目的地.该包可能在任意一个节点产生,我们需要知道该网络中一共有多少 ...