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;
}
}
}
首先,join是一个同步方法
关键代码:
while (isAlive()) {
wait(0); //如果 timeout 为零,则不考虑实际时间,在获得通知前该线程将一直等待。
}
isAlive是 join方法的本意和目标。即使中间被唤醒(虚拟唤醒),他仍然会再次调用wait(0)来等待下一次通知。
最终,线程死的时候会调用自己的notifyAll方法,join会执行结束。
当main线程调用t.join时候,main线程会获得线程对象t的锁(wait 意味着拿到该对象的锁),调用该对象的wait(等待时间),直到该对象唤醒main线程
是main线程调用对象t的join()方法:(这里的t == Object的作用, 线程t仍在运行,则执行Object t的wait()) 调度的结果是 main一直等待。
因此,main会执行t的wait()方法,会等待直到t运行结束。
所以阻塞的是main线程。
wait(long)的方法说明:当前线程必须拥有此对象监视器。在其他线程调用此对象的notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待
此方法导致当前线程(称之为 T)将其自身放置在对象的等待集中,然后放弃此对象上的所有同步要求。
出于线程调度目的(执行的动作是让出且等待。 等待某个条件发生 isAlive,队列可读,队列可写。。),在发生以下四种情况之一前,线程 T 被禁用,且处于休眠状态:
1)其他某个线程调用此对象的 notify 方法,并且线程 T 碰巧被任选为被唤醒的线程。
2)其他某个线程调用此对象的 notifyAll 方法。
3)其他某个线程中断线程 T。
4)大约已经到达指定的时间。如果 timeout 为零,则不考虑实际时间,在获得通知前该线程将一直等待。
然后,从对象的等待集中删除线程 T,并重新进行线程调度。然后,该线程以常规方式与其他线程竞争,以获得在该
对象上同步的权利;一旦获得对该对象的控制权,该对象上的所有其同步声明都将被恢复到以前的状态,这就是调
用wait 方法时的情况。然后,线程 T 从 wait 方法的调用中返回。所以,从 wait 方法返回时,该对象和线程T 的同
步状态与调用wait 方法时的情况完全相同。
在没有被通知、中断或超时的情况下,线程还可以唤醒一个所谓的虚假唤醒 (spurious wakeup,唤醒时,条件仍然不满足)。虽然这种情况在实
践中很少发生,但是应用程序必须通过以下方式防止其发生,即对应该导致该线程被提醒的条件进行测试,如果不
满足该条件,则继续等待。换句话说,等待应总是发生在循环中,如下面的示例:
synchronized (obj) {
while (<condition does not hold>)
obj.wait(timeout);
... // Perform action appropriate to condition
}
http://blog.csdn.net/hai_qing_xu_kong/article/details/43917141