• Java java.lang.Thread#join()方法分析


    结论:A 线程调用 B 线程对象的 join 方法,则 A 线程会被阻塞,直到 B 线程 挂掉 (Java Doc 原话: Watis for this thread to die)。

    一、分析

    查看源代码:

    public final void join() throws InterruptedException {
            join(0); //得接着看这个带参数的方法,这里传入 0 表示等待时间为永久
    }

    带参数的 join:

    public final synchronized void join(long millis)  // 注意这里的 synchronized  关键字,A 线程 获取了 B 线程对象的锁,所以下面的代码中才可以调用 wait 方法
    throws InterruptedException {
    long base = System.currentTimeMillis();
    long now = 0;

    if (millis < 0) {
    throw new IllegalArgumentException("timeout value is negative");
    }

    if (millis == 0) { // 参数为 0
    while (isAlive()) { // 等到死为止
    wait(0); // 这是 Object 对象的 wait 方法,调用了这个方法的线程(A 线程)会阻塞
    }
    } else { // 等待参数指定的时间
    while (isAlive()) {
    long delay = millis - now;
    if (delay <= 0) {
    break;
    }
    wait(delay);
    now = System.currentTimeMillis() - base;
    }
    }
    }

    到这里,基本可以得出开头的结论了。

    但是,开头的结论并不十分严谨,因为线程 A 其实并不是一直阻塞直到线程 B 挂掉的:

    while (isAlive()) {
        wait(0); //真正让线程 A 阻塞的是这个方法的调用
    }

    当 进入 wait(0) 时,线程 A 阻塞,但 wait(0) 返回时,线程 A 唤醒,但是 while 循环条件如果满足的话 (线程 B 还没死),线程 A 再次阻塞。

    线程 A 一直在 join 方法里,在阻塞和唤醒之间不断切换状态,直到线程 B 挂掉。

    二、应用场景

    为什么要让线程 A 阻塞,直到线程 B 挂掉呢?

    假如:线程 B 在做一个耗时的计算,线程 A 需要这个计算的结果,并且线程 A 没有其他事要做了,只想得到计算结果,那么线程 A 就可以 调用线程 B 对象 的 join 方法,

               让自己阻塞,等线程 B 挂掉(计算结束),取得计算结果。

  • 相关阅读:
    Android ListView和CheckBox应用之批量删除操作(附带源码)
    Spring3 MVC 3到Spring MVC框架简介
    Struts2.3 + Spring3.1 + Hibernate3.6 + HTML5 + CSS3整合开发
    Java和MongoDB之Hello World
    SQL Server 2008中的hierarchyid
    SQLSERVER复制表的方法
    去掉struts2标签的样式
    KineticJS教程(12)
    SQL Server日期时间格式转换字符串详解
    生活不易,且行且珍惜!
  • 原文地址:https://www.cnblogs.com/justmehyp/p/9996220.html
Copyright © 2020-2023  润新知