为什么 wait() 总是在循环中调用
2022-08-31 12:20:47
我已经读到,我们应该总是从循环中调用a:wait()
while (!condition) { obj.wait(); }
它没有循环就可以正常工作,所以为什么呢?
我已经读到,我们应该总是从循环中调用a:wait()
while (!condition) { obj.wait(); }
它没有循环就可以正常工作,所以为什么呢?
您不仅需要循环它,还需要在循环中检查您的条件。Java 不保证您的线程只会被 notify()/notifyAll() 调用或正确的 notify()/notifyAll() 调用唤醒。由于此属性,无循环版本可能会在开发环境中工作,并在生产环境中意外失败。
例如,您正在等待某些内容:
synchronized (theObjectYouAreWaitingOn) {
while (!carryOn) {
theObjectYouAreWaitingOn.wait();
}
}
一个邪恶的线程出现了:
theObjectYouAreWaitingOn.notifyAll();
如果邪恶的线程没有/不能搞砸你只是继续等待正确的客户端。carryOn
编辑:添加了更多示例。等待可能会中断。它抛出中断的异常,你可能需要将等待包装在一个尝试捕获中。根据您的业务需求,您可以退出或禁止显示异常并继续等待。
它在 Object.wait(long milis) 的文档中得到了解答。
线程也可以在不被通知、中断或超时的情况下唤醒,即所谓的虚假唤醒。虽然这在实践中很少发生,但应用程序必须通过测试应该导致线程被唤醒的条件,并在不满足条件时继续等待来防止这种情况。换句话说,等待应该总是在循环中发生,就像这样:
synchronized (obj) {
while (<condition does not hold>)
obj.wait(timeout);
... // Perform action appropriate to condition
}
(有关此主题的更多信息,请参阅Doug Lea的“Java中的并发编程(第二版)”(Addison-Wesley,2000)中的第3.2.3节,或Joshua Bloch的“Effective Java Programming Language Guide”(Addison-Wesley,2001)中的项目50。