今天偶然看了下join()的源码,产生一个问题,明明是在被调者的方法中调用了wait()方法,为啥就把调用者给阻塞了呢?如下代码。
public class JoinTest {
public static void main(String []args)throws InterruptedException{
Thread t = new Thread(()->{
for (int i = 0; i < 5 ; i++) {
//为了效果明显,加上等待时间
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我是"+Thread.currentThread().getName()+",我执行完main线程才能继续向下执行");
}
});
t.start();
t.join();
System.out.println("我是"+Thread.currentThread().getName()+",我执行完了");
}
}

join()源码,wait()是在被调者的方法里写的,对此我很疑惑,怎么做到在被调者中执行wait()却把调用者阻塞掉的。
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;
}
看看API里面的wait()方法是怎么介绍的
它说是使得当前线程等待,那们我们自己写一个类,把join()方法稍作修改,看看运行join()时当前线程到底是谁
public class MyTry {
public static void main(String []args) throws InterruptedException{
TestB t = new TestB();
t.start();
t.join2(0);
System.out.println("我是主线程,我要执行完啦");
}
}
class TestB extends Thread{
@Override
public void run() {
while(true){
try {
Thread.sleep(3000);
System.out.println("我是TestB...");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public final synchronized void join2(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
//看看执行join()的时候,当前线程是谁
System.out.println("我是"+Thread.currentThread().getName()+"我在执行join2()");
while (isAlive()) {
wait(0);
}
} else {
System.out.println("我是"+Thread.currentThread().getName());
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
}
发现阻塞在这里了,并且当前线程的确是调用者-----main线程,至此,原因便一目了然。main调用t对象的join()方法的时候,相当于调用一个普通对象的普通方法,并不是t线程去执行这个join(),而这个join()的执行线程还是main线程,所以等待的还是main线程。
本文通过分析join()源码和实验,探讨了为何调用线程的join()方法会导致调用者线程被阻塞,揭示了wait()方法在join()中的作用以及线程执行的实质。
608

被折叠的 条评论
为什么被折叠?



