join()底层原理是基于对象监视器的wait/notify机制:调用线程以目标线程为锁,循环检查isAlive(),存活则wait()挂起;目标线程终止时JVM自动notifyAll()唤醒。

Java 中 join() 方法实现线程同步的底层原理,核心是“在目标线程对象上执行 wait(),靠 JVM 在其终止时自动 notifyAll()”——它不是轮询,也不是让目标线程停住,而是让调用者安全挂起、精准唤醒。
基于对象监视器的 synchronized + wait/notify
join() 是 Thread 类的 synchronized 实例方法,锁对象就是被 join 的那个线程实例(比如 t.join() 中的 t)。JVM 会:
- 进入以
t为锁的同步块 - 循环检查
t.isAlive() - 若
t还活着,就调用t.wait()—— 此刻当前线程释放t的锁、进入 WAITING 状态、不再消耗 CPU - 一旦
t执行结束(状态变为 TERMINATED),JVM 底层自动触发t.notifyAll(),唤醒所有在t上等待的线程
为什么必须用 wait(),而不是 sleep() 或 yield()
因为只有 wait() 能同时满足三个关键要求:
- 必须在同步上下文中调用,确保
isAlive()判断和挂起动作的原子性 - 主动释放锁,避免阻塞其他可能需要修改线程状态的操作(如
start()或 JVM 内部状态更新) - 可被精确唤醒:不依赖时间猜测,也不靠反复检查,完全由 JVM 在线程终结时通知
超时版 join(long millis) 的实际行为
它不是简单调一次 wait(millis) 就完事,而是:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 每次
wait()返回后,重新计算剩余等待时间 - 如果剩余时间 ≤ 0,直接退出等待
- 如果
t.isAlive()已为false(即t提前结束),立即跳出循环
这样既支持“最多等多久”,也支持“一结束立刻响应”,兼顾确定性和及时性。
容易踩坑的关键点
理解原理后,这几个细节常被忽略:
-
t.join()阻塞的是当前线程,t自己照常运行 - 必须在
t.start()之后调用,否则isAlive()为false,方法直接返回,根本不等 - 所有
join()重载都声明抛出InterruptedException,因为底层用了wait();捕获后建议恢复中断状态:Thread.currentThread().interrupt() - 绝对不要对当前线程自己调用
join()(如Thread.currentThread().join()),会导致自死锁

















