JAVA join()方法

时间:2023-01-07 09:54:31

转自: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&lpar;&rpar; sleep&lpar;&rpar; notify&lpar;&rpar; start&lpar;&rpar; join&lpar;&rpar;方法 等

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

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

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

  4. 简谈Java的join&lpar;&rpar;方法

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

  5. Java多线程中的join&lpar;&rpar;方法

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

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

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

  7. Java中join&lpar;&rpar;方法的理解

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

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

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

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

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

随机推荐

  1. StackPanel在增加控件的问题

    今天遇到这样一个问题,就是我做了一个自定义控件.然后加到StackPanel中, <StackPanel Height="676" HorizontalAlignment=& ...

  2. 【读书笔记】iOS-Xcode-模拟器操作的一些快捷键

    Cmd+1/2/3       可以切换模拟器的显示比例. Option+Shift     可以在模拟器中调出双指拖动效果. Option      可以在模拟器中调出双指放大缩小效果. Comma ...

  3. JavaScript案例四:全选练习

    JavaScript实现全选,全不选等效果... <!DOCTYPE html> <html> <head> <title>JavaScript全选练习 ...

  4. 轻松解决在一个虚拟主机上运行多个 ASP&period;NET 网站应用

    不知道有没有朋友像我一样会遇到这样一个问题: 在网上购买 .NET 空间,由于虚拟主机的限制,你并不能把某个目录设为一个独立的应用,或者一些价格比较高的空间,虽然可以设置,但数量也是有限的.这个问题导 ...

  5. usb协议分析-设备描述符配置包-描述符

    /* usb协议分析仅供大家参考---设备描述符配置包,设备描述符, 地址设置, 配置描述符, 字符串描述符 */ /* -1- usb设备描述符配置包 */ typedef struct _USB_ ...

  6. c&num;与java webservice调用问题

    问题描述一: c#调用java写的websrevice,对方接收到的参数与实际传的值不一致,返回的时候值也获取不到,为null. 该参数为普通的string类型,因此不存在类型转换的问题. 处理: 使 ...

  7. PB C&sol;S轉B&sol;S ODBC方式連接數據庫

    PB C/S轉B/S ODBC方式連接數據庫,DSN需要建為系統而不是使用者DSN,否則連不上數據庫.

  8. 安装酷痞到IIS7&period;x共用80端口Windows&lpar;64位&rpar;系统下运行多个酷痞

    需求: 1.酷痞直接运行的模式是自宿主运行.由于win系统一般都由iis提供多个网站服务,并首先占用了80端口,如果想酷痞可以直接通过主机头和iis共用80端口会出现这种运行模式的需求. 以下是实现方 ...

  9. 《笨方法学Python》加分题16

    基础部分 # 载入 sys.argv 模块,以获取脚本运行参数. from sys import argv # 将 argv 解包,并将脚本名赋值给变量 script :将参数赋值给变量 filena ...

  10. POJ 1056 IMMEDIATE DECODABILITY 【Trie树】

    <题目链接> 题目大意:给你几段只包含0,1的序列,判断这几段序列中,是否存在至少一段序列是另一段序列的前缀. 解题分析: Trie树水题,只需要在每次插入字符串,并且在Trie树上创建节 ...