join()的用法:join()方法是调用者轮询来查看该线程的alive状态,调用者使用 t1.join()来等待t1线程结束。
join()源码
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;
}
}
}
t1.join()的等价写法:
synchronized (t1) {
// 调用者线程进入 t1 的 waitSet 等待, 直到 t1 运行结束
while (t1.isAlive()) {
t1.wait(0);
}
}
完整的代码
public static void main(String[] args) throws Exception {
Thread t1 = new Thread(() -> {
System.out.println("t1先执行");
}, "t1");
Thread t2 = new Thread(() -> {
try {
synchronized (t1) {
// 调用者线程进入 t1 的 waitSet 等待, 直到 t1 运行结束
while (t1.isAlive()) {
t1.wait(0);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t2后执行");
}, "t2");
t1.start();
t2.start();
}
打印:
t1先执行
t2后执行
刚开始的时候我是很懵逼的,因为可以发现,t1.wait(0)后【把t1直接看成一个普通对象,此时t2线程释放对象锁进入WAITING状态】,并没有相应的notifyAll()/notify()方法来将t2线程唤醒,那为什么能够打印"t2后执行"呢?
这里的一个重大知识点是,t1.wait()后是如何唤醒线程的?
通过看join()的文档:
As a thread terminates the {@code this.notifyAll} method is invoked。 当一个线程终止时,notifyAll方法会被调用。
所以,当t1线程终止时,会隐式地调用t1.notifyAll()方法,从而唤醒了t2线程,让t2的代码继续执行。