thread.join()是让当前线程等待目标线程执行完毕后再继续运行,从而实现线程间顺序控制;它通过阻塞调用线程直至目标线程终止(terminated状态)来同步执行逻辑,底层基于wait/notify机制,支持无参、超时参数及纳秒精度重载版本。

Thread.join() 是让当前线程等待目标线程执行完毕后再继续运行,从而实现线程间的顺序控制。它不是“强制线程按顺序启动”,而是通过“等待”来保证执行逻辑的先后关系。
join 的基本作用机制
调用 thread.join() 时,当前线程(比如主线程)会阻塞,直到 thread 执行完成(即 run() 方法结束或线程自然终止)。这本质上是利用线程状态同步,而非加锁或共享变量。
- join() 底层依赖 JVM 的 wait/notify 机制,被 join 的线程结束后会唤醒等待它的线程
- join() 可带超时参数(如 join(5000)),避免无限等待
- 若目标线程已结束,join() 立即返回,不会阻塞
用 join 实现 A→B→C 顺序执行
假设有三个任务需严格按顺序执行:先执行线程 A,再 B,最后 C。只需在启动后依次 join:
Thread a = new Thread(() -> System.out.println("A"));
Thread b = new Thread(() -> System.out.println("B"));
Thread c = new Thread(() -> System.out.println("C"));
a.start();
a.join(); // 主线程等 A 结束
b.start();
b.join(); // 主线程等 B 结束
c.start();
c.join(); // 主线程等 C 结束
这样就能确保输出一定是 A → B → C,即使各线程内部耗时不同、调度随机,join 仍能串行化执行效果。
注意 join 调用的位置和对象
常见误区是在线程 start 前调用 join,或对错误对象调用 —— 这会导致无效或异常:
- 必须在 start() 之后 调用 join(),否则等待一个未启动的线程无意义
- join() 是实例方法,只能对已创建的 Thread 对象调用,不能对 Runnable 或静态方法使用
- 不要在被 join 的线程内部调用自身的 join(会造成自等待死锁)
- 多个线程同时 join 同一个线程是安全的,JVM 内部已处理并发等待
join 与 sleep、wait 的关键区别
join 容易和 Thread.sleep()、Object.wait() 混淆,但语义不同:
- sleep() 是让当前线程休眠指定时间,不释放锁,也不依赖其他线程状态
- wait() 需在 synchronized 块中调用,释放锁并等待 notify,面向对象级协作
- join() 专为线程生命周期同步设计,语义清晰:等它跑完再走
所以实现线程顺序执行时,join 更直接、更安全,无需手动维护状态标志或同步块。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











