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才会收到通知被唤醒,然后继续执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值