Java 多线程基础(九)join() 方法
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() 方法的更多相关文章
- Java多线程中的join()方法
		
一.join()方法介绍 join() 定义在Thread.java中.join()方法把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程.比如在线程B中调用了线程A的join( ...
 - 浅谈Java多线程中的join方法
		
先上代码 新建一个Thread,代码如下: package com.thread.test; public class MyThread extends Thread { private String ...
 - Java多线程中的join方法
		
新建一个Thread,代码如下: package com.thread.test; public class MyThread extends Thread { private String name ...
 - java多线程中关于join方法的使用
		
Thread的非静态方法join()让一个线程B"加入"到另外一个线程A的尾部.在A执行完毕之前,B不能工作.例如: Thread t = new MyThread ...
 - Java多线程10:join()方法
		
一.前言 通过一个简单的例子引入join()方法 public class Thread01 extends Thread{ @Override public void run() { for(int ...
 - 多线程基础知识---join方法
		
join方法的作用 thread.join()方法用于把指定的线程加入到当前线程中,把当前线程的CPU执行时间让给另一个线程.比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继 ...
 - Java并发编程--多线程中的join方法详解
		
Java Thread中, join()方法主要是让调用该方法的thread在完成run方法里面的部分后, 再执行join()方法后面的代码 例如:定义一个People类,run方法是输出姓名年龄. ...
 - [转]Java多线程干货系列—(一)Java多线程基础
		
Java多线程干货系列—(一)Java多线程基础 字数7618 阅读1875 评论21 喜欢86 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们 ...
 - Java 多线程——基础知识
		
java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...
 
随机推荐
- 非静态代码块(非static初始化块)&静态代码块(static初始化块)
			
非静态代码块: TestOrder: package com.aff.singleton; /* 类的第四个成员:初始化块(代码块) 代码块: 如果有修饰的话只能使用static 分类:非静态代码块: ...
 - 正则表达式:匹配单个数字重复n次
			
匹配单个数字重复n次:(\d)\1{n-1}其中,\d表示一位数字,(\d)表示匹配之后捕获该匹配,并分组并对组进行编号\1表示被捕获的第一个分组{n-1}是因为被捕获的第一个分组已经消耗了一位数字, ...
 - [Pyspark]RDD常用方法总结
			
aggregate(zeroValue, seqOp, combOp) 入参: zeroValue表示一组初值 Tuple seqOp表示在各个分区partition中进行 什么样的聚合操作,支持不同 ...
 - tomcat session漏洞反序列化详解
			
1. 条件1)攻击者可以控制服务器上的文件名/文件内容2)tomcat context配置了persistencemanager的fileSotre3) persistenceManager 配置了s ...
 - 磨刀-CodeWarrior11生成的Makefile解析
			
https://mp.weixin.qq.com/s/plvviDFLsLQeg9ZeP_3WMA 一. 简介 Code Warrior 11是基于Eclipse CDT开发的集成开发环境(IDE ...
 - JavaWeb项目:旅游网站【涉及各种知识】
			
JQuery异步请求(ajax) $.ajax({ // 请求方式为get或者post等 type: "GET", // 服务器响应的数据类型 dataType: "js ...
 - 面试题: MySQL 索引失效的10大原因
			
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 1.建表: CREATE TABLE staffs ( id INT PRIMARY KEY AUTO_ ...
 - Java实现 蓝桥杯 算法提高 求arccos值
			
算法提高 7-2求arccos值 时间限制:10.0s 内存限制:256.0MB 提交此题 问题描述 利用标准库中的cos(x)和fabs(x)函数实现arccos(x)函数,x取值范围是[-1, 1 ...
 - Java实现 蓝桥杯VIP 算法提高 夺宝奇兵
			
算法提高 夺宝奇兵 时间限制:1.0s 内存限制:512.0MB [题目描述] 在一座山上,有很多很多珠宝,它们散落在山底通往山顶的每条道路上,不同道路上的珠宝的数目也各不相同.下图为一张藏宝地图: ...
 - Java实现蓝桥杯历届试题区间移位
			
问题描述 数轴上有n个闭区间D1,-,Dn.其中区间Di用一对整数[ai, bi]来描述,满足ai < bi.已知这些区间的长度之和至少有10000.所以,通过适当的移动这些区间,你总可以使得他 ...