我正在实现逻辑来理解等待和通知工作,当我使用线程扩展类时,我发现了一些我无法分析的东西,然后等待和通知按预期工作,但是当我实现可运行的接口时,输出会有所不同
public class AdderThread extends Thread {
int total;
@Override
public void run() {
synchronized (this) {
for (int i = 0; i < 1000; i++) {
total += i;
}
notify();
}
}
public class WaitNotify {
public static void main(String[] args) {
AdderThread addrTh = new AdderThread();
addrTh.start();
// -1243309312
System.out.println("Total without Wait() " + addrTh.total);
}
}
当实现 Runnable 给我正确的答案时,这意味着它正在等待线程完成任务,但当我使用扩展线程时,它给我的答案为 0,即它不是在等待线程完成任务。
public class WaitNotify {
public static void main(String[] args) {
AdderThread addrTh = new AdderThread();
addrTh.start();
// -1243309312
System.out.println("Total Before Wait " + addrTh.total);
synchronized (addrTh) {
try {
System.out.println("Waiting for Sum...");
addrTh.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Total " + addrTh.total);
}
}
}
你的新线程可以在主线程调用 'wait() 之前调用notify()
。" 在这种情况下,wait() 调用将永远等待,因为如果其他线程尚未等待它,notify() 根本不会执行任何操作。
wait()
和 notify()
是旨在以非常特定的方式使用的低级操作:
请参阅 Java wait() 不会被 notify() 唤醒以获取更多信息。
实现Runnable
的情况与扩展Thread
的情况之间的区别是由于this
在第一种情况下引用匿名内部类,而在后一种情况下引用Thread
对象。
这很重要,因为线程机制使用 wait() 和 notify() 来实现自己的目的。 因此,如果您的wait()
调用来得太晚,无法被代码中的notify()
调用唤醒,它仍可能被库代码中的notify()
唤醒(例如,当线程终止时)。 当您实现Runnable
时,这不会发生,因为库没有理由通知它。