关于Thread类的join()阻塞当前线程以等待子线程处理完毕疑问?

来源:8-4 如何实现处理线程的返回值

慕斯4415754

2019-06-01

老师,使用Thread类的join()阻塞当前线程以等待子线程处理完毕,您使用了t.join()来阻塞当前线程,但为什么没有去显示唤醒,而是等待子线程处理完毕?(您在讲线程状态中,没有设置Timeout参数的Thread.join()方法会进入无限期等待,需要被显示唤醒),期待您的解答,谢谢。

写回答

1回答

翔仔

2019-06-02

同学好,视频里调用没有参数的join去等待子线程处理完毕是符合预期的,不需要显示唤醒呢,我们可以看看它的源码

public final void join() throws InterruptedException {
    join(0);
}

public final synchronized void join(long millis)
throws InterruptedException {
    long base = System.currentTimeMillis();
    long now = 0;

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

    if (millis == 0) {
        while (isAlive()) {
            wait(0);
        }
    } else {
        while (isAlive()) {
            long delay = millis - now;
            if (delay <= 0) {
                break;
            }
            wait(delay);
            now = System.currentTimeMillis() - base;
        }
    }
}

public final synchronized void join(long millis, int nanos)
throws InterruptedException {

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

    if (nanos < 0 || nanos > 999999) {
        throw new IllegalArgumentException(
                            "nanosecond timeout value out of range");
    }

    if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
        millis++;
    }

    join(millis);
}

其中

1. join() 和 join(long millis, int nanos) 最后都调用了 join(long millis)。

2. 带参数的 join() 都是 synchronized method。

3. join() 调用了 join(0),从源码可以看到 join(0) 不断检查当前线程(join() 所属的线程实例,非调用线程)是否是 Active。

4. join() 和 sleep() 一样,都可以被中断(被中断时,会抛出 InterrupptedException 异常);不同的是,join() 内部调用了 wait(),会出让锁,而 sleep() 会一直保持锁。

正因为会一直检查状态,如果被调用的线程一直是alive的话,调用join的线程会让出锁直至被调用的线程完成,就会接着执行,因此不需要显示唤醒呀

1
2
翔仔
回复
慕斯4415754
同学好,不矛盾哈,已经回答了 http://coding.imooc.com/learn/questiondetail/123604.html
2019-06-03
共2条回复

剑指Java面试-Offer直通车 百度资深面试官授课

招聘季即将到来,让百度资深面试官来为你的高薪Offer保驾护航

8427 学习 · 1870 问题

查看课程