Java中join()方法通过阻塞调用线程直至目标线程终止来实现执行顺序同步,本质是等待而非控制,基于monitor锁和wait()/notifyAll()机制,需在目标线程start()后调用且不可自join。

Java 中 join() 方法实现线程执行顺序的强制同步,核心在于“阻塞当前线程,直到目标线程终止”。它不改变线程调度策略,也不加锁共享资源,而是通过**主动让渡执行权 + 等待通知机制**达成逻辑上的先后依赖。
本质是等待而非控制
join() 不干预目标线程怎么跑,只约束“谁可以继续往下走”。调用 t2.join() 的线程(比如主线程)会暂停自身执行,进入 WAITING 状态,直到 t2 的 run() 方法彻底返回、线程状态变为 TERMINATED,JVM 内部自动触发 notifyAll() 唤醒等待者。
- 它底层基于目标线程对象的 monitor 锁和
wait()/notifyAll()实现,不是轮询 - 阻塞的是调用方线程,不是被 join 的线程——t2 仍在独立运行
- 一旦 t2 死亡,所有在它身上调用过
join()的线程都会被唤醒(即使已超时或被中断)
两种典型用法对应不同场景
实现“T1 → T2 → T3”顺序,关键不在 start 顺序,而在 join 的嵌套或串行安排:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
主线程串行控制(适合简单流程):先
t1.start(),立刻t1.join();等 t1 结束后,再t2.start()和t2.join();同理处理 t3。效果是伪并发——任一时刻最多一个子线程活跃 -
子线程主动依赖(适合解耦与复用):t2 的
run()开头写t1.join(),t3 的run()开头写t2.join(),然后三者都start()(顺序任意)。t2 启动后自己等 t1,t3 启动后自己等 t2,主线程无需介入协调
必须注意的硬性前提
看似简单的方法,踩坑多因忽略基础约束:
立即学习“Java免费学习笔记(深入)”;
- 必须在目标线程
start()之后调用join(),否则对未启动线程调用会立即返回,起不到等待作用 -
join()声明抛出InterruptedException,不能忽略——要么捕获并恢复中断状态(Thread.currentThread().interrupt()),要么向上声明 - 不要对已终止线程反复调用
join(),虽安全但无意义;更不能在目标线程内部调用自身join()(死锁)
它不是万能的,也有明确边界
join() 只解决“等结束”这一件事,无法处理更复杂的协作需求:
- 不能等待“执行到某一步”,只能等整个
run()完结 - 无法实现“T1 执行一半 → T2 开始 → T1 继续”这类交错执行
- 多个线程同时
join()同一个线程,它们之间仍无序,只是共同延迟到该线程结束后才启动 - 若需精确阶段控制(如生产者-消费者、信号量协调),应配合
Lock + Condition或CountDownLatch等工具

















