转自: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. 一些稍微复杂点的sql语句

    UPDATE test SET content = REPLACE(content,'国家级',''),content = REPLACE(content,'世界级',''),content = RE ...

  2. Git系列教程三 配置与基本命令

    一.安装Git 网上有很多安装教程,可以参考.这里使用的是Windows版本的Git,点击这里下载. 二.基本设置 安装完成后,通过点击鼠标右键就可以看到新添加了俩个Git命令:Git GUI Her ...

  3. uwsgi 安装配置

    安装uwsgi# pip install uwsgi 配置uwsgi:首先要明确的是,如果你喜欢用命令行的方式(如shell)敲命令,那可以省去任何配置.但是,绝大多数人,还是不愿意记那么长的命令,反 ...

  4. How to use wget ?

    1.How to get conent (not download page) of website? wget <websit> -q -O -

  5. js按键监听

    //回车键监听 function keypressed(){ if(event.keyCode == 13) { doAction(); } } document.onkeydown = keypre ...

  6. GridView实现方块布局

    效果如下: 先创建一个BaseViewHolder package com.example.griddemo; import android.util.SparseArray; import andr ...

  7. 理解AX InventTrans的几种状态

    接触AX一段时间后,发现InventTrans表非常重要.它可以说是物流模块的核心,开发BI报表的话必须依赖此报表.   先来看官方释义: InventTrans表包含了库存交易的信息.当销售/采购订 ...

  8. LeetCode Find the Celebrity

    原题链接在这里:https://leetcode.com/problems/find-the-celebrity/ 题目: Suppose you are at a party with n peop ...

  9. Sublime WiFi真机同步和WiFi真机预览使用说明

    概述WiFi真机同步: 通过在Sublime中建立调试服务,接收真机设备主动连接调试的方式,配合apploader及自定义loader,为开发者提供在局域网内通过WiFi实现应用快速真机同步和实时预览 ...

  10. inotify监控目录变化重启服务器tornado项目

    pycharm 配置了提交服务器项目每次pycharm修改后,虽然保存到服务器但是项目还得自己去服务器kill再启动.就花几分钟写了shell脚本用于监控项目目录变化并重启tornado项目的脚本 如 ...