join()方法使当前线程等待目标线程执行完毕后再继续运行,需在已启动的线程上调用;支持超时等待和中断处理,多个join()调用按顺序阻塞实现串行等待。

在 Java 中,join() 方法用于让当前线程(通常是主线程)**等待调用 join() 的线程执行完毕后再继续运行**,是实现线程同步等待最直接、最常用的方式。
join 的基本用法
join() 是 Thread 类的实例方法,必须在目标线程对象上调用。它会让当前线程阻塞,直到目标线程自然结束(即 run() 方法执行完成)。
- 调用前,目标线程必须已启动(即已调用
start()),否则join()不会起作用(未启动的线程调用join()会立即返回) - 不能在自己身上调用
join()(比如在run()方法里对this.join()),会导致死锁 - 多个线程可依次调用
join(),实现串行等待
示例:
Thread t1 = new Thread(() -> {
System.out.println("t1 开始");
try { Thread.sleep(2000); } catch (InterruptedException e) {}
System.out.println("t1 结束");
});
t1.start();
t1.join(); // 主线程在此等待 t1 完成
System.out.println("主线程继续执行");
带超时的 join(避免无限等待)
join(long millis) 和 join(long millis, int nanos) 允许设置最大等待时间。若超时前目标线程仍未结束,当前线程会自动恢复执行。
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 超时后,目标线程仍在后台运行,不会被中断或终止
- 适合对响应性有要求的场景,比如防止某个任务拖慢整体流程
- 调用后建议检查目标线程状态(如
t.isAlive())判断是否真的结束了
示例:
t1.start();
t1.join(3000); // 最多等 3 秒
if (t1.isAlive()) {
System.out.println("t1 还没结束,但主线程不再等待");
} else {
System.out.println("t1 已顺利完成");
}
多个线程的等待顺序与组合
当需要等待多个子线程全部完成时,可以按需调用多个 join()。注意:它们是**顺序阻塞**的,不是并行等待。
- 如果想“同时”等待多个线程(即等所有都结束),只需依次调用
join()即可——因为主线程只有一条执行流,顺序调用等效于等待全部完成 - 若希望更清晰地管理多个线程,可用
ExecutorService配合Future.get()或CountDownLatch,但join()是最轻量、无需额外依赖的选择 - 不要在循环中对未启动的线程调用
join(),应确保start()在join()之前
常见写法:
Thread t1 = new Thread(() -> {/*...*/});
Thread t2 = new Thread(() -> {/*...*/});
t1.start();
t2.start();
t1.join(); // 等 t1
t2.join(); // 再等 t2
System.out.println("t1 和 t2 都已完成");
join 与 interrupt 的关系
正在执行 join() 的线程可被中断。一旦被中断,会抛出 InterruptedException,且当前线程的中断状态会被清除。
- 捕获异常后,通常需决定是否恢复中断状态(
Thread.currentThread().interrupt()) - 被中断的
join()会立即返回,不继续等待 - 目标线程(被 join 的那个)不受影响,仍正常运行
示例:
t1.start();
try {
t1.join();
} catch (InterruptedException e) {
System.out.println("等待被中断");
Thread.currentThread().interrupt(); // 恢复中断标记
}

















