join() 等待目标线程彻底终止(TERMINATED状态),内部通过wait/notifyAll实现;必须先start()再join(),否则无效;带参join仅设超时上限,需配合isAlive()检查实际状态。

Java 中 join() 方法让当前线程暂停执行,直到目标线程的 run() 方法彻底结束、进入 TERMINATED 状态为止。它不是“等线程开始”或“等某个动作完成”,而是严格等待线程生命周期终结。
join() 等的是什么
它等的是目标线程对象自身的终止状态。内部通过在该 Thread 实例上加锁并调用 wait() 实现阻塞,当目标线程退出 run() 方法时,JVM 会自动触发 notifyAll() 唤醒所有等待它的线程。
- 目标线程已结束(
isAlive() == false):join() 立即返回,不阻塞 - 目标线程正在运行:当前线程进入 WAITING 状态,释放 CPU,不消耗资源
- 目标线程处于 NEW 或 TERMINATED 状态:join() 不做任何等待,直接返回
必须先 start() 再 join()
顺序错误是常见失效原因。只有调用了 start(),线程才真正进入 RUNNABLE 状态,join() 才有等待意义。
- ✅ 正确:
t.start(); t.join(); - ❌ 错误:
t.join(); t.start();(此时线程还是 NEW,join() 瞬间返回) - ❌ 错误:
new Thread(() -> {}).join();(没 start,无法启动,自然无法等待)
超时等待与状态检查
带参数的 join(long millis) 只控制“最多等多久”,不保证“等到了”。超时后必须手动检查是否真完成了:
立即学习“Java免费学习笔记(深入)”;
-
t.join(3000);表示主线程最多停 3 秒,之后无论 t 是否还在跑,都会继续执行 - 超时后应立即调用
t.isAlive()判断实际状态,不能仅靠是否超时做逻辑分支 -
join(0)和无参join()完全等价,表示无限等待
多线程场景下的正确写法
每个线程都需要单独调用 join(),不能只等最后一个:
- 启动多个线程后,应统一先
start(),再逐个join(),避免串行启动拖慢整体速度 - 若线程数量较多,可用
List<thread></thread>存储后遍历调用,但注意仍需处理InterruptedException - 不推荐在
synchronized(threadObj)块内调用threadObj.join(),易引发语义混乱或死锁


















