我收到了修复旧项目中声纳问题的请求,有这样的代码段,对此函数的每次调用都将暂停50ms:
synchronized(monitor) {
[...]
try {
[...]
Thread.sleep(config.getWaitTime()); // return 50
} catch (SomeException e) {
log.error(e.getMessage(), e);
}
[...]
}
首先,声纳要求我将Thread.sleep()
更改为wait()
,所以我将try块更改为:
try {
[..]
monitor.wait(config.getWaitTime());
} catch (SomeException e) {
log.error(e.getMessage(), e);
}
然后,出现另一个问题:Remove this call to "wait" or move it into a "while" loop
,我在多线程方面没有太多经验,所以我不确定我的解决方法是否正确:
boolean wait = true;
while (wait) {
wait = false;
monitor.wait(config.getWaitTime());
}
以上解决方案正确吗?如果没有,我该怎么办?
答案 0 :(得分:2)
线程也可以在不被通知,中断或未唤醒的情况下唤醒 超时,即所谓的虚假唤醒。虽然这种情况很少发生 实际上,应用程序必须通过测试 应该导致线程唤醒的情况,以及 如果不满足条件,则继续等待。 换句话说, 等待应该总是循环发生,就像这样:
synchronized (obj) { while (<condition does not hold>) obj.wait(timeout); ... // Perform action appropriate to condition }
您的循环效果不好,应该是这样的:
while (wait) {
monitor.wait(config.getWaitTime());
}
当不再需要等待条件时,必须从其他位置设置wait
变量。
答案 1 :(得分:1)
while
似乎很无助:
boolean wait = true;
while (wait) {
wait = false;
monitor.wait(config.getWaitTime());
}
while
语句周围的wait()
语句旨在检查如果wait()
中的逻辑/功能条件为{{1 }},但在您的情况下,它永远不会因为您将等待分配给while
作为while正文的第一条语句。
true
太无助了。
这是与{关联的Object.wait(long)
javadoc:
线程也可以在不被通知,中断或未唤醒的情况下唤醒 超时,即所谓的虚假唤醒。虽然这种情况很少发生 实际上,应用程序必须通过测试 应该导致线程唤醒的情况,以及 如果条件不满足,将继续等待。
通常,我对Sonar的建议并不信服。...
您可以使用计时器检查所需时间是否已过。但是ugg。
我建议您保持适合您需求的Thread方法。
或者,如果您想使工具API添加无助的代码。我当然在开玩笑:别那样!
答案 2 :(得分:1)
声纳要求我将Thread.sleep()更改为wait()
在这里忽略声纳。这是误报。