转自: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. 分享一个前辈的NPOIhelper

    即拿即用: 首先要下载npoi的dll,此不赘述,接着添加引用: using NPOI.HPSF; using NPOI.HSSF.UserModel; using NPOI.SS.UserModel ...

  2. [转载] Win7KB3146706补丁导致蓝屏0x0000006B的修复方案

    进入winpe,将附件的蓝屏6B修复补丁kb3146706.zip的补丁替换windows/system32下面的ci.dll文件,里面有64和32位系统的,替换了文件就可以进入系统了. 启动进入系统 ...

  3. 初探Redis+Net在Windows环境下的使用

    Redis官网地址:https://redis.io/:Redis官方暂时不支持Windows环境,但是MicroSoft Open Tech group开发了一个Windows平台下运行的版本. R ...

  4. notepad++快捷键大全

    Ctrl+C 复制 Ctrl+X 剪切 Ctrl+V 粘贴 Ctrl+Z 撤消 Ctrl+Y 恢复 Ctrl+A 全选 Ctrl+F 键查找对话框启动 Ctrl+H 查找/替换对话框 Ctrl+D 复 ...

  5. android studio 2.0 GPU Debugger使用说明

    GPU Debugger GPU Debugging Tools The GPU debugging tools are an experimental feature intended to hel ...

  6. KnocKout 绑定数据

    Controller 里面的方法: public ActionResult Index() { return View(); } [HttpPost] public JsonResult Reader ...

  7. rbd snap(1)

    来自官方文档: 快照介绍 快照是映像在某个特定时间点的一份只读副本. 对当前镜像打过快照以后,Active层仍在当前镜像,快照文件为只读. Note 如果在做快照时映像仍在进行 I/O 操作,快照可能 ...

  8. SpringMVC常用配置-文件上传-基于Servlet 3.0

    [2] http://www.cnblogs.com/weilu2/p/springmvc_MultipartConfigElement_tomcat_webapps_work.html

  9. Java c3p0连接池

    import java.beans.PropertyVetoException; import java.sql.Connection; import java.sql.SQLException; i ...

  10. MOSS(Microsoft Office Sharepoint Server)升级2013遇到的PDF权限问题及解决方案

    最近公司MOSS从2007升级到了2013,遇到了一个很呕心的问题: 为了保护公司资料安全,我们一直使用RMS给文档增加权限(信息权限管理 (IRM)),只有公司内部员工可以阅读.RMS加权限的范围仅 ...