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. 循序渐进VUE+Element 前端应用开发(3)--- 动态菜单和路由的关联处理

    在我开发的很多系统里面,包括Winform混合框架.Bootstrap开发框架等系列产品中,我都倾向于动态配置菜单,并管理对应角色的菜单权限和页面权限,实现系统对用户权限的控制,菜单一般包括有名称.图 ...

  2. NO.2 TI开发环境的搭建 SDK+Code Composer Studio

    首先我们要了解TI嵌入式开发环境 对于TI嵌入式开发,首先我们要下载SDK软件包,其次要准备编译环境Code Composer Studio. 对于SDK的下载,可以在官网浏览http://www.t ...

  3. [工具-004]如何从apk中提取AndroidManifest.xml并提取相应信息

    跟上一篇类似,我们也需要对APK的一些诸如umengkey,ADkey,TalkingData进行验证,那么我们同样需要解压apk文件,然后提取其中的AndroidManifest.xml.然后解析x ...

  4. [Objective-C] 016_UI篇_UIView(上)

    在我们使用app时屏幕上能看到的UI元素(按钮,列表,图片...),我们称之为视图,都是继承与UIView,它们通常有着位置,大小,背景颜色等属性,在appl中视图和窗口展示了应用的用户界面,同时负责 ...

  5. C语言 俄罗斯方块demo

    这是我的第一篇随笔,当然是发我写的第一个游戏啦! 大一(本人现在大二)寒假过完年,在家待着想起放假前计划写一个游戏的,因为本人立志走游戏开发这条路,加上大一上册学了C语言,就想写个游戏练练手.想了很久 ...

  6. leetcode56之合并区间

    题目描述: 给出一个区间的集合,请合并所有重叠的区间. 示例: 输入: [[1,3],[2,6],[8,10],[15,18]]输出: [[1,6],[8,10],[15,18]]解释: 区间 [1, ...

  7. 添加对docker的监控

    一.环境:已安装docker机器ip:192.168.0.202 二.原理 使用docker的metrics-add参数,提供对docker运行参数的访问条件. 三.修改/etc/docker/dae ...

  8. Rocket - util - HeterogeneousBag

    https://mp.weixin.qq.com/s/5hNM4yeQjaLvAJzgMG9PGQ   介绍HeterogeneousBag的实现.   ​​   1. 基本介绍   一个口袋(bag ...

  9. Java实现LeetCode_0020_ValidParentheses

    package javaLeetCode.primary; import java.util.Scanner; import java.util.Stack; public class ValidPa ...

  10. Java实现第九届蓝桥杯书号验证

    书号验证 2004年起,国际ISBN中心出版了<13位国际标准书号指南>. 原有10位书号前加978作为商品分类标识:校验规则也改变. 校验位的加权算法与10位ISBN的算法不同,具体算法 ...