转自:http://www.open-open.com/lib/view/open1371741636171.html

一、为什么要用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是Thread类的一个方法,启动线程后直接调用,例如:

Thread t = new AThread(); t.start(); t.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));
    else
    do
    {
    if(!isAlive())
    break;
    long l3 = l - l2;
    if(l3 <= 0L)
    break;
    wait(l3);
    l2 = System.currentTimeMillis() - l1;
    } while(true);
    }

JAVA join()方法的更多相关文章

  1. java join 方法的使用

    在很多情况下,主线程创建并启动子线程,如果子线程中要进行大量的耗时运算,主线程往往将早于子线程结束之前结束.这时,如果主线程想等待子线程执行完成之后再结束,比如子线程处理一个数据,主线程要取得这个数据 ...

  2. 【多线程】java多线程 测试例子 详解wait() sleep() notify() start() join()方法 等

    java实现多线程,有两种方法: 1>实现多线程,继承Thread,资源不能共享 2>实现多线程  实现Runnable接口,可以实现资源共享 *wait()方法 在哪个线程中调用 则当前 ...

  3. Java线程中yield与join方法的区别

    长期以来,多线程问题颇为受到面试官的青睐.虽然我个人认为我们当中很少有人能真正获得机会开发复杂的多线程应用(在过去的七年中,我得到了一个机会),但是理解多线程对增加你的信心很有用.之前,我讨论了一个w ...

  4. 简谈Java的join()方法

    join()是Thread类的一个方法.根据jdk文档的定义: public final void join()throws InterruptedException: Waits for this ...

  5. Java多线程中的join()方法

    一.join()方法介绍 join() 定义在Thread.java中.join()方法把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程.比如在线程B中调用了线程A的join( ...

  6. java多线程 join方法以及优先级方法

    /*join:当A线程执行到了B线程的.join()方法时,A就会等待.等B线程都执行完,A才会执行. join可以用来临时加入线程执行. 1.线程使用join方法,主线程就停下,等它执行完,那么如果 ...

  7. Java中join()方法的理解

    thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程. 比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B. t.join ...

  8. Java并发编程--多线程中的join方法详解

    Java Thread中, join()方法主要是让调用该方法的thread在完成run方法里面的部分后, 再执行join()方法后面的代码 例如:定义一个People类,run方法是输出姓名年龄. ...

  9. 模拟做饭系统(java+线程中的join方法)

    (一)项目框架分析 妈妈要去做饭,发现没有酱油,让儿子去买酱油,然后回来做饭. 根据面向对象的思想,有两个对象,妈妈和儿子 主要有两个方法: (一)没有线程控制(即儿子没有买酱油回来妈妈就做好饭了)+ ...

随机推荐

  1. p4lang/switch make bm-switchsai 出现内存不足导致的Error

    报错如下: Compiling : bm::dc.cpp g++: internal compiler error: Killed (program cc1plus) Please submit a ...

  2. logoff remote desktop sessions via command line tools

    This trick I learned from my one of ex-college.  In Windows servers, only two remote desktop session ...

  3. Sharepoint client model 中出现Cannot invoke HTTP DAV request. There is a pending query 的解决办法

    由于近期在某项目中使用sharepoint client 对象模型做项目 在sharepoint 2010环境下正常,但迁移到sharepoint 2013后报错,提示如下 Cannot invoke ...

  4. java中的接口interface

    关于接口 接口描述了实现了它的类拥有什么功能.因为Java是强类型的,所以有些操作必须用接口去约束和标记.接口作为类的能力的证明,它表明了实现了接口的类能做什么. 类似与class,interface ...

  5. Oracle知识分类之常见规范

    命名规范 变量规范 1.入参,统一以I_前缀开头,且不能省略IN 2.出参,统一以O_前缀开头 3.局部变量,统一以V_前缀开头 4.常量,统一以CN_前缀开头 5.游标,统一以CUR_前缀开头 组成 ...

  6. Linux-001-nmon系统性能监控工具的使用及报表产出

    在进行性能测试的时候,需要获取服务器的各项指标,例如 CPU.MEM.I/O.DISK 等.网上有很多的监控工具,nmon 就是其中的一个,其可与 JMeter结合使用,测试系统的性能.其概要的介绍, ...

  7. 尝试自己翻译了FreeCodeCamp的文章,技术方面多认识了几种技术,文章标题:Transparency in Action Free Code Camp is Now Open Source

    这是FreeCodeCamp其中一篇文章,趁着学习英文的时间,翻译这篇文章,其中讲到作者创建FCC过程,本文属于原创,第一次翻译,翻译还有诸多不足之处,请大家包含. 原文地址:https://medi ...

  8. Asp.net Mvc Entity Framework Code First 数据库迁移

    1.创建Mvc项目 2.安装Entity Framework 2.1.如下图打开程序包管理器控制台: 2.2.输入命令Install-Package EntityFramework,即可安装Entit ...

  9. Java中的Atomic包使用指南

    Atomic包介绍 在Atomic包里一共有12个类,四种原子更新方式,分别是原子更新基本类型,原子更新数组,原子更新引用和原子更新字段.Atomic包里的类基本都是使用Unsafe实现的包装类. 原 ...

  10. SQLite如何测试

    原文 http://www.sqlite.org/testing.html 目录 1. 介绍 1.1. 执行总结 2. 测试套件 3.异常测试 3.1 内存溢出测试 3.2 I/O错误测试 3.3 c ...