一、使用方式。

join是Thread类的一个方法,启动线程后直接调用,例如:

Thread t = new AThread(); t.start(); t.join();

二、为什么要用join()方法

在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后,需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到join()方法了。

三、join方法的作用

在JDk的API里对于join()方法是:

join

public final void join() throws InterruptedException Waits for this thread to die. Throws: InterruptedException  - if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown.

即join()的作用是:“等待该线程终止”,这里需要理解的就是该线程是指的主线程等待子线程的终止。也就是在子线程调用了join()方法后面的代码,只有等到子线程结束了才能执行。

四、用实例来理解

写一个简单的例子来看一下join()的用法:

1.AThread 类

  1. BThread类

  2. TestDemo 类

    class BThread extends Thread {public BThread() {super("[BThread] Thread");};public void run() {String threadName = Thread.currentThread().getName();System.out.println(threadName + " start.");try {for (int i = 0; i < 5; i++) {System.out.println(threadName + " loop at " + i);Thread.sleep(1000);}System.out.println(threadName + " end.");} catch (Exception e) {System.out.println("Exception from " + threadName + ".run");}}
    }
    class AThread extends Thread {BThread bt;public AThread(BThread bt) {super("[AThread] Thread");this.bt = bt;}public void run() {String threadName = Thread.currentThread().getName();System.out.println(threadName + " start.");try {bt.join();System.out.println(threadName + " end.");} catch (Exception e) {System.out.println("Exception from " + threadName + ".run");}}
    }
    public class TestDemo {public static void main(String[] args) {String threadName = Thread.currentThread().getName();System.out.println(threadName + " start.");BThread bt = new BThread();AThread at = new AThread(bt);try {bt.start();Thread.sleep(2000);at.start();at.join();} catch (Exception e) {System.out.println("Exception from main");}System.out.println(threadName + " end!");}
    }

    打印结果:

    main start.    //主线程起动,因为调用了at.join(),要等到at结束了,此线程才能向下执行。
    [BThread] Thread start.
    [BThread] Thread loop at 0
    [BThread] Thread loop at 1
    [AThread] Thread start.    //线程at启动,因为调用bt.join(),等到bt结束了才向下执行。
    [BThread] Thread loop at 2
    [BThread] Thread loop at 3
    [BThread] Thread loop at 4
    [BThread] Thread end.
    [AThread] Thread end.    // 线程AThread在bt.join();阻塞处起动,向下继续执行的结果
    main end!      //线程AThread结束,此线程在at.join();阻塞处起动,向下继续执行的结果。

    修改一下代码:

    public class TestDemo {public static void main(String[] args) {String threadName = Thread.currentThread().getName();System.out.println(threadName + " start.");BThread bt = new BThread();AThread at = new AThread(bt);try {bt.start();Thread.sleep(2000);at.start();//at.join(); //在此处注释掉对join()的调用} catch (Exception e) {System.out.println("Exception from main");}System.out.println(threadName + " end!");}
    }

    打印结果:

    main start.    // 主线程起动,因为Thread.sleep(2000),主线程没有马上结束;[BThread] Thread start.    //线程BThread起动
    [BThread] Thread loop at 0
    [BThread] Thread loop at 1
    main end!   // 在sleep两秒后主线程结束,AThread执行的bt.join();并不会影响到主线程。
    [AThread] Thread start.    //线程at起动,因为调用了bt.join(),等到bt结束了,此线程才向下执行。
    [BThread] Thread loop at 2
    [BThread] Thread loop at 3
    [BThread] Thread loop at 4
    [BThread] Thread end.    //线程BThread结束了
    [AThread] Thread end.    // 线程AThread在bt.join();阻塞处起动,向下继续执行的结果

    五、从源码看join()方法

    在AThread的run方法里,执行了bt.join();,进入看一下它的JDK源码:

    public final void join() throws InterruptedException {join(0L);
    }

    然后进入join(0L)方法:

    public final synchronized void join(long l)throws InterruptedException
    {long l1 = System.currentTimeMillis();long l2 = 0L;if(l < 0L)throw new IllegalArgumentException("timeout value is negative");if(l == 0L)for(; isAlive(); wait(0L));elsedo{if(!isAlive())break;long l3 = l - l2;if(l3 <= 0L)break;wait(l3);l2 = System.currentTimeMillis() - l1;} while(true);
    }

    单纯从代码上看: * 如果线程被生成了,但还未被起动,isAlive()将返回false,调用它的join()方法是没有作用的。将直接继续向下执行。 * 在AThread类中的run方法中,bt.join()是判断bt的active状态,如果bt的isActive()方法返回false,在bt.join(),这一点就不用阻塞了,可以继续向下进行了。从源码里看,wait方法中有参数,也就是不用唤醒谁,只是不再执行wait,向下继续执行而已。 * 在join()方法中,对于isAlive()和wait()方法的作用对象是个比较让人困惑的问题:

    isAlive()方法的签名是:public final native boolean isAlive(),也就是说isAlive()是判断当前线程的状态,也就是bt的状态。

    wait()方法在jdk文档中的解释如下:

    Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. In other words, this method behaves exactly as if it simply performs the call wait(0).

    The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.

    在这里,当前线程指的是at。

Java Thread.join()详解相关推荐

  1. C#,JAVA各版本之Thread.join()详解

    join方法的功能就是使异步执行的线程变成同步执行.也就是说,当调用线程实例的start方法后,这个方法会立即返回,如果在调用start方法后后需要使用一个由这个线程计算得到的值,就必须使用join方 ...

  2. java threas.jion_Java Thread.join详解

    使用方法 Thread t = new ThreadA(); t.start(); t.join(); 为什么要用 join() 方法 在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的 ...

  3. Java并发编程之Thread类详解

    Thread类详解: 线程(Thread): 是操作系统进行调度的最小单位,Java中的线程是对操作系统线程的封装.本文从线程的创建到停止结合代码和具体实例分析一下关于java线程的一些常见问题. 线 ...

  4. 4.6 W 字总结!Java 11—Java 17特性详解

    作者 | 民工哥技术之路 来源 | https://mp.weixin.qq.com/s/SVleHYFQeePNT7q67UoL4Q Java 11 特性详解 基于嵌套的访问控制 与 Java 语言 ...

  5. 5W字高质量java并发系列详解教程(上)-附PDF下载

    文章目录 第一章 java.util.concurrent简介 主要的组件 Executor ExecutorService ScheduledExecutorService Future Count ...

  6. java多线程设计模式详解[推荐]

    java多线程设计模式详解[推荐] java多线程设计模式详解之一 线程的创建和启动 java语言已经内置了多线程支持,所有实现Runnable接口的类都可被启动一个新线程,新线程会执行该实例的run ...

  7. 【狂神说Java】多线程详解

    [狂神说Java]多线程详解 1.任务 生活中的例子.边吃饭.边玩手机 开车.打电话.挂点滴 上厕所.玩手机 现实中太多这样同时做多件事情的例子了,看起来是多个任务都在做,其实本质上我们的大脑在同一时 ...

  8. Java内存溢出详解之Tomcat配置

    Java内存溢出详解 转自:http://elf8848.iteye.com/blog/378805 一.常见的Java内存溢出有以下三种: 1. java.lang.OutOfMemoryError ...

  9. java基础(十三)-----详解内部类——Java高级开发必须懂的

    java基础(十三)-----详解内部类--Java高级开发必须懂的 目录 为什么要使用内部类 内部类基础 静态内部类 成员内部类 成员内部类的对象创建 继承成员内部类 局部内部类 推荐博客 匿名内部 ...

最新文章

  1. 算法精解:DAG有向无环图
  2. IOS4.x下UIWebView的显示问题
  3. Excel中这四个常出错的地方,你一定中过!
  4. python 支付宝个人账单_金融支付财务融合业务-实践分享1:订单、账单、交易流水、账套知识解构、原理解析...
  5. MySQL replace into (insert into 的增强版)
  6. 工作3年和工作7年的程序员到底差在哪里?
  7. HTML期末作业-美食点餐网页
  8. VS2017——50G超豪华IDE套餐酸爽体验!
  9. distinct sql用法_十分钟搞懂SQL数据分析
  10. mini车f和r的区别_雪铁龙也造出了“老头乐”,外观复古时尚,叫板宏光MINI?...
  11. 最简单的基于FFmpeg的AVfilter的例子-纯净版
  12. kvm中内存过载使用
  13. 如何使用免费工具构建有效的小型APP开发团队
  14. php订单号生成规则,项目笔记之订单号生成规则以及方法,第一篇!
  15. 小米路由器 网站服务器地址,小米路由器设置网址
  16. C语言小项目——电子秒表(毫秒级)
  17. 偏最小二乘法PLS和PLS回归的介绍及其实现方法
  18. 爬虫实战 ——百度翻译
  19. win7连接sftp_WinSCP官方版下载_WinSCP(SFTP客户端) v5.17.1中文版 - Win7旗舰版
  20. 详解java -jar命令及SpringBoot通过java -jav启动的过程

热门文章

  1. vs2019安装C#环境并新建窗体项目
  2. python时间序列峰值检测_python – 二维数组中的峰值检测
  3. C++_类和动态内存分配2-改进后的String类
  4. nodejs模块加载分析(1).md
  5. 【关于重载OnBackPressed无效的解决方案】
  6. 将用户添加至sudoers列表
  7. Quasar Akka Vertx Norbert 比较
  8. 802.11n 连接的建议设置是什么?
  9. css(hr元素)水平线的定位
  10. LVTRM架构发布0.1测试版