如何解决声纳问题"Remove this call to "等待" or move it into a " " loop"?



我收到一个修复遗留项目中声纳问题的请求,有一个这样的代码段,对该函数的每次调用都将暂停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());
}

上述解决方案正确吗?如果没有,我该怎么办?

从Object#wait((Java文档

线程也可以在不被通知、中断或超时,所谓的虚假唤醒。虽然这种情况很少发生在实践中,应用程序必须通过测试本应导致线程被唤醒的条件,以及如果条件不满足,则继续等待换句话说,等待应该总是发生在循环中,就像下面这样:

synchronized (obj) {
while (<condition does not hold>)
obj.wait(timeout);
... // Perform action appropriate to condition
}

你的循环看起来不太好,应该是这样的:

while (wait) {
monitor.wait(config.getWaitTime());
}

当不再需要等待条件时,必须从其他地方设置wait变量。

此处while显得无助:

boolean wait = true;
while (wait) {
wait = false;
monitor.wait(config.getWaitTime());
}

wait()语句周围的while语句旨在检查如果while中的逻辑/函数条件是true,是否会重新调用wait(),但在您的情况下,它永远不会,因为您将等待分配给false作为while主体的第一个语句
while太无助了
这是与关联的Object.wait(long)javadoc

线程也可以在不被通知、中断或超时,所谓的虚假唤醒。虽然这种情况很少发生在实践中,应用程序必须通过测试本应导致线程被唤醒的条件,以及如果条件不满足,则继续等待。

我经常不相信Sonar的建议
您可以使用计时器来检查所需的时间是否已过。但是ugg
我建议你保持适合你要求的线程方式
或者如果您想让工具API添加无助的代码。我当然是在开玩笑:不要那样做!

sonar要求我将Thread.sleep((更改为wait((

忽略此处的声纳即可。这是误报。

最新更新