如何解决Sonar问题“将此呼叫移至“等待”或将其移至“ while”循环”?

时间:2018-12-12 08:18:55

标签: java multithreading sonarqube

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

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

3 个答案:

答案 0 :(得分:2)

Object#wait() Java doc

  

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

 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()

在这里忽略声纳。这是误报。