Thread类提供了让一个线程等待另一个线程完成的方法——join()方法。
当在某个程序执行流中调用其他线程的join()方法时,调用线程将被阻塞,直到被join()方法加入的join线程执行完为止。
join()方法通常由使用线程的程序调用,以将大问题划分成许多小问题,每个小问题分配一个线程。当所有的小问题都得到处理后,再调用主线程来进一步操作。
直接看他的源码:
/*
等待这个线程死掉。
调用此方法的行为完全相同
作为调用的方式
<块引用>
{@linkplain #join(long) 加入}{@code (0)}
@throws 中断异常
如果任何线程中断了当前线程。这当前线程的中断状态是抛出此异常时清除。
*/
public final void join() throws InterruptedException {
join(0);
}
再深入这个 join(0)
内部调用了一个wait 实现线程阻塞

注意这里的wait是 Object的native wait方法是将当前线程阻塞,而不是将当前调用的对象的线程阻塞,当前线程是主线程,所以主线程会阻塞。
当子线程执行完后,他会去唤醒main继续执行。

原理图如下所示:

join内部调用 Object的native wait方法是将当前线程阻塞,而不是将当前调用的对象的线程阻塞,当前线程是主线程,所以主线程会阻塞,当子线程执行完后,他会去唤醒main继续执行。
启动子线程后,立即调用该线程的join()方法,则主线程必须等待子线程执行完成后再执行
package com.yyl.threadTest;
public class TestThreadMethod {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
try {
System.out.println("等3s再执行");
Thread.sleep(3000);
System.out.println("3s后了可以执行了");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程执行了");
});
thread.start();
thread.join();
System.out.println("主线程执行了");
}
}
运行结果如下:

如果不加join,主线程就不会等待直接输出,如下所示
