thread.join() 讓呼叫線程(通常是主線程)等待目標線程執行結束後才繼續。本質是呼叫線程在目標線程的 join() 方法內循環調用 wait()。
public final void join() throws InterruptedException { join(0); }
public final synchronized void join(long millis) throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) throw new IllegalArgumentException("timeout value is negative");
if (millis == 0) {
while (isAlive()) wait(0); // 永久等待
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) break;
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
關鍵點:wait() 讓當前執行線程(主線程)進入等待,而非目標線程。
public class JoinTest {
public static void main(String[] args) {
try {
ThreadA t1 = new ThreadA("t1");
t1.start();
t1.join(); // 主線程阻塞直到 t1 結束
System.out.printf("%s finish%n", Thread.currentThread().getName());
} catch (InterruptedException e) { e.printStackTrace(); }
}
static class ThreadA extends Thread {
@Override public void run() {
System.out.printf("%s start%n", getName());
for (int i = 0; i < 1_000_000; i++); // 模擬耗時
System.out.printf("%s finish%n", getName());
}
}
}
t1 start
t1 finish
main finish
t1.join() 進入阻塞。main finish。誤以為 t1.join() 是讓 t1 等待。實際上 join() 是 Thread 實例方法,但內部 wait() 作用於呼叫者(主線程)。
t1.join(2000) 最多等待 2 秒,超時後主線程自動繼續,不拋異常。需配合 t1.isAlive() 判斷是否正常結束。