【Java 深入学习】join 再理解
基本介绍
昨天我突然想到一个问题 join 方法的底层实现是 wait,执行 wait 的线程等待,那么它是怎么唤醒的呢?抱着这个问题我找了找博客最后发现了这篇文章【Java深入学习】多线程之join方法 - 掘金 (juejin.cn)),这里面介绍了 notifyAll 的解锁时机,我发现了这么一段话在 java 中,Thread 类线程执行完 run()方法后,一定会自动执行 notifyAll()方法 这句话如同醍醐灌顶,我立刻就理解了 join 方法里的 wait 是如何唤醒的了。接下来我来模拟一下 join 的过程。
模拟
我们关注两个地方,第一是 while 循环条件 isAlive()它的作用是 判断调用 join 的线程是否存活 如果存活则执行 wait()这里 wait 作用的线程是执行 join 的线程,注意这里 调用和执行的区别。举一个例子:我们在 t2 线程中执行了 t1.join(),那么 isAlive()判断的是 t1 线程是否存活,wait 是让 t2 线程陷入等待
代码示例
15:08:50.125 c.TestInterJoin [t1] - t115:08:50.127 c.TestInterJoin [t1] - t115:08:50.127 c.TestInterJoin [t1] - t115:08:50.127 c.TestInterJoin [t1] - t115:08:50.127 c.TestInterJoin [t1] - t115:08:50.127 c.TestInterJoin [t2] - t215:08:50.128 c.TestInterJoin [t2] - t215:08:50.128 c.TestInterJoin [t2] - t215:08:50.128 c.TestInterJoin [t2] - t215:08:50.128 c.TestInterJoin [t2] - t2
解释:
我们创建了两个线程 t1 t2,我们在 t2 线程中执行 t1.join 使得 t1 线程同步到 t2 线程,结果也能证明这个结论
用 wait 模拟 join 例子
结果:
15:12:16.361 c.TestInterJoinMN [t1] - t1
15:12:16.363 c.TestInterJoinMN [t1] - t1
15:12:16.363 c.TestInterJoinMN [t1] - t1
15:12:16.363 c.TestInterJoinMN [t1] - t1
15:12:16.363 c.TestInterJoinMN [t1] - t1
15:12:16.363 c.TestInterJoinMN [t2] - t2
15:12:16.363 c.TestInterJoinMN [t2] - t2
15:12:16.363 c.TestInterJoinMN [t2] - t2
15:12:16.363 c.TestInterJoinMN [t2] - t2
15:12:16.363 c.TestInterJoinMN [t2] - t2
解释:
我们发现我们在 t2 线程创建了一个以 t1 线程对象为监视器的锁,并执行了 wait()方法导致 t2 线程陷入等待,此时如果我们没有 notify 或 notifyAll 方法的话 是不能唤醒 t2 线程的,但这里神奇的事情出现了 我们发现最终 t2 线程还是执行了。原因还是这句话在 java 中,Thread 类线程执行完 run()方法后,一定会自动执行 notifyAll()方法,因为我们是把 t1 线程当成锁对象,但随着 t1 线程的运行结束 即 run 方法运行结束 t1 线程执行了 t1.notifyAll(),所以此时唤醒了 所有以 t1 为锁的线程,所以 t2 线程被唤醒了。这就是 join 的实现原理。
版权声明: 本文为 InfoQ 作者【Geek_65222d】的原创文章。
原文链接:【http://xie.infoq.cn/article/f50ca490b5f1fd7d7a5044d72】。未经作者许可,禁止转载。
评论