写点什么

【Java 深入学习】join 再理解

作者:Geek_65222d
  • 2022 年 10 月 09 日
    河南
  • 本文字数:1375 字

    阅读完需:约 5 分钟

基本介绍

昨天我突然想到一个问题 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 例子

@Slf4j(topic = "c.TestInterJoinMN")public class TestInterJoinMN {    public static void main(String[] args) {        Thread t1 = new Thread(()->{            Sleeper.sleep(2);            for (int i=0;i<5;i++){                log.debug("t1");            }        },"t1");
Thread t2 = new Thread(()->{ synchronized (t1){ try { t1.wait(); } catch (InterruptedException e) { e.pri(ntStackTrace(); } } for (int i=0;i<5;i++){ log.debug("t2"); } },"t2"); t2.start(); t1.start(); }}
复制代码


结果:


  • 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 的实现原理。

发布于: 刚刚阅读数: 3
用户头像

Geek_65222d

关注

还未添加个人签名 2022.09.09 加入

还未添加个人简介

评论

发布
暂无评论
【Java深入学习】join再理解_十月月更_Geek_65222d_InfoQ写作社区