首页 > 解决方案 > 如何解决声纳问题“删除此调用以“等待”或将其移动到“while”循环中?

问题描述

我收到了修复遗留项目中的声纳问题的请求,有这样的代码段,每次调用此函数都会暂停 50 毫秒:

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

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

标签: javamultithreadingsonarqube

解决方案


来自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当不再需要等待条件时,必须从别处设置该变量。


推荐阅读