我已经了解到,在等待一个对象时,条件应该放在一个循环中而不是在一个if condition
内。其中一个原因是避免可能发生的各种虚假唤醒呼叫。
例如:
synchronized (obj) {
while (condition is false) {
obj.wait(5 * 1000);
}
... do something ...
}
但是,我只想等待5秒钟才能通知线程。在上面的代码中,线程等待5秒。但在那段时间之后,如果情况仍然是假的,我们会再次等待。如果我有以下情况,情况就不是这样了:
synchronized (obj) {
if (condition is false) {
obj.wait(5 * 1000);
}
... do something ...
}
但这与指南相矛盾,我们应该使用循环而不是单个if条件!
这是如何解决的?
答案 0 :(得分:2)
这是我通常如何处理这个问题:
long timeout = ....;
synchronized(obj) {
long start = System.currentTimeMillis();
while(!condition && (timeout > 0)) {
obj.wait(timeout);
long now = System.currentTimeMillis();
timeout -= (now - start);
start = now;
}
}
答案 1 :(得分:1)
回答我自己的问题,这可能有用:
synchronized (obj) {
for (long time = System.currentTimeMillis() + timeout; !condition && System.currentTimeMillis() < time; ) {
obj.wait(time - System.currentTimeMillis());
}
if (condition) {
... do something ...
}
}