在下面的语句中,即使没有调用通知,也会执行 wait()
方法,但语句below wait()
仅在线程完成执行后执行laurel
。
我尝试使用其他对象锁定 hardy 块的同步,这次等待方法仍然永远等待,有人可以解释为什么执行 wait()
后的语句吗?
package delagation;
public class Solution extends Thread {
static Thread laurel, hardy;
public static void main(String[] args) throws InterruptedException {
laurel = new Thread() {
public void run() {
System.out.println("A");
try {
hardy.sleep(1000);
} catch (Exception e) {
System.out.println("B");
}
System.out.println("C");
}
};
hardy = new Thread() {
public void run() {
System.out.println("D");
try {
synchronized(laurel) {
laurel.wait();
//wait method is called here,
//There is not notify in this class,
//but the statement below are executing
System.out.println(Thread.currentThread().getName());
}
} catch (Exception e) {
System.out.println("E");
}
System.out.println("F");
}
};
laurel.setName("laurel");
hardy.setName("hardy");
laurel.start();
hardy.start();
}
}
你不需要假设一个虚假的唤醒来解释这里发生了什么。当 laurel 终止时,它会向正在等待它的线程发送通知。(这就是 Thread.join 的工作方式。
请参阅 Thread#join 的 api 文档:
此实现使用 this.wait 调用的循环,条件为 this.isAlive。当线程终止时,将调用 this.notifyAll 方法。建议应用程序不要在 Thread 实例上使用等待、通知或通知全部。
此外,始终使用条件在循环中等待;请参阅 Oracle 并发教程,尤其是受保护块页面。(从描述中,您可以看到 join 等待在一个循环中,其中测试的条件在连接到的线程上是 isAlive,所以这是一个很好的例子。您可以在 Thread 类的 jdk 源代码中找到联接方法。