先看代码:
public static void main(String[] args) {
Thread son = new Thread(() -> {
Thread.sleep(5000);
System.out.println("im thread son!!!");
});
son.start();
son.join();
System.out.println("im thread main!!!");
}
运行结果;
im thread son!!!
im thread main!!!
join的JDK源码:
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;
}
}
}
注意方法上的synchronized字段(锁的资源是this对象)
调用 thread.join() 相当于join(long millis) 方法中传入的参数为0;
所以源码实际上生效的代码段为:
while (isAlive()) {
wait(0);
}
}
如果线程是alive状态的就死循环调用 wait(0)方法,所以调用 thread.join() 方法的地方,相当于同时调用了thread.wait(),
因此调用thread.join()方法的线程会被阻塞,保证子线程执行完再执行主线程。
把这段生效代码挪到主线程中,替代join方法:
public static void main(String[] args) {
Thread son = new Thread(() -> {
Thread.sleep(5000);
System.out.println("im thread son!!!");
});
son.start();
// son.join(); 相当于下面的代码
synchronized(son) {
while(son.isAlive()) {
//阻塞了主线程。 son既是线程,又是竞争的锁对象
son.wait(0);
}
}
System.out.println("im thread main!!!");
}
运行结果仍然是;
im thread son!!!
im thread main!!!
两段代码的代码含义完全一样,第二段代码用join中的源码替代了join但更 易于理解join的原理。
在thread执行完成的时候会调用notify() 方法,调用join方法的地方就会继续执行。