Java join()使用及源码分析

Java join()使用及源码分析

(先铺垫下,最后上源码)
首先再说一下join()方法的作用:若在父线程main中创建了一个子线程son,如果父线程需要等待子线程执行完再执行,则在父线程main中调用son.join();即可

官方解释:join() method suspends the execution of the calling thread until the object called finishes its execution.
即:son.join()方法阻塞调用此方法的线程(calling thread),直到线程son完成,此线程(main)再继续

还有几点需要注意

  1. wait()方法调用后会释放锁,并阻塞当前线程,等待notify。
  2. notify()方法调用后并不会释放锁。
  3. wait() notify()方法都必须在同步的代码中调用。

关于jion()的简单例子

public class JoinDemo {
    public static void main(String[] args) {
        try {
            System.out.println("main running");
            SonThread sonThread = new SonThread();
            sonThread.start();
            System.out.println("main suspend and waiting for son");
            sonThread.join();
            System.out.println("son did his work, main running");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class SonThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("son running ..." + i);
        }
    }
}

/** 输出:
main running
main suspend and waiting for son
son running ...0
son running ...1
son running ...2
son running ...3
son running ...4
son did his work, main running
**/

可以看到main线程阻塞并等到son线程完成后才继续执行了。

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;
            }
        }
    }

从源码中可以看到其实join()内部是调用了wait()方法的。
接着分析下,

上面的例子中是通过sonThread.join();这段代码调用了join()的,join()是一个synchronize方法,其锁对象也就是this,在上面的例子中,也就是sonThread对象。所以sonThread.join()其实就相当于如下:

public class JoinDemo {
    public static void main(String[] args) {
       //...

        synchronized (sonThread){
                sonThread.wait();
                //...
            }
        
       //...
    }
}

再返回上面说的:wait()方法调用后会释放锁,并阻塞当前线程
那么当前线程是哪个线程呢?
join()的调用位于main Thread的main()中,所以这里当然就是阻塞main Thread了。所以sonThread.join()调用后,main Thread会阻塞起来。

那么main Thread被阻塞后是在哪收到notify而继续运行的呢?你可能在源码中找不到是哪notify了。
其实,这个过程涉及到了JVM底层了。son线程执行完毕了exit过程会有一个notifyall操作

以上面的例子来最后总结一下:sonThread.join() 这个调用表示mainThread将在锁对象sonThread上进行wait()等待,直到sonThread线程运行完成后mainThread才会收到通知被唤醒,然后继续执行。

参与评论 您还未登录,请先 登录 后发表或查看评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:编程工作室 设计师:CSDN官方博客 返回首页

打赏作者

一个行走的民

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值