java join()源码_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)再继续

还有几点需要注意

wait()方法调用后会释放锁,并阻塞当前线程,等待notify。

notify()方法调用后并不会释放锁。

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`join()` 方法是 `Thread` 类中的一个方法,它的作用是让调用该方法的线程等待该线程执行完毕。当一个线程使用 `join()` 方法时,调用线程会被阻塞,直到被调用线程执行完毕后才会继续执行。 下面是 `join()` 方法的源码: ``` public final void join() throws InterruptedException { join(0); } ``` 可以看到,`join()` 方法实际上是调用了另一个重载方法 `join(long millis)`,并将参数设置为 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(long millis)` 方法是一个同步方法,它首先对传入的参数进行检查,如果小于 0,则会抛出异常。 如果传入的参数为 0,则调用 `wait(0)` 方法,这会使当前线程进入等待状态,直到被调用线程执行完毕后才会被唤醒。 如果传入的参数不为 0,则会在循环中检查被调用线程是否还活着,如果还活着,则调用 `wait(delay)` 方法,这会使当前线程进入等待状态,等待一定的时间后被唤醒。在每次循环中,都会更新当前时间 `now`,并计算需要等待的时间 `delay`。 如果被调用线程已经执行完毕或者等待时间已经超过了传入的参数,则会跳出循环,方法执行完毕。 总的来说,`join()` 方法的本质是利用了 `wait()` 和 `notify()` 方法实现线程的同步和等待。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值