Java并发-虚假唤醒和等待(超时)

Java并发-虚假唤醒和等待(超时),java,concurrency,Java,Concurrency,我了解到,当等待一个对象时,条件应该放在循环中,而不是放在单个if condition中。这样做的一个原因是为了避免可能发生的各种虚假唤醒调用 例如: synchronized (obj) { while (condition is false) { obj.wait(5 * 1000); } ... do something ... } 但是,我只想等待5秒钟,等待线程得到通知。在上面的代码中,线程等待5秒钟。但在这段时间之后,如果条件仍然为假,我们将

我了解到,当等待一个对象时,条件应该放在循环中,而不是放在单个
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条件的指导方针相矛盾


这是如何解决的?

回答我自己的问题,这可能有用:

synchronized (obj) {
    for (long time = System.currentTimeMillis() + timeout; !condition && System.currentTimeMillis() < time; ) {
        obj.wait(time - System.currentTimeMillis());
    }
    if (condition) {
        ... do something ...
    }
}
synchronized(obj){
对于(长时间=System.currentTimeMillis()+超时;!条件和System.currentTimeMillis()
我通常是这样处理的:

long timeout = ....;
synchronized(obj) {
  long start = System.currentTimeMillis();
  while(!condition && (timeout > 0)) {
    obj.wait(timeout);
    long now = System.currentTimeMillis();
    timeout -= (now - start);
    start = now;
  }
}

您可以在进入循环之前记住当前时间,如果唤醒时经过了给定的时间段,则使条件为真。当然是Doh。好主意!我回答了我自己的问题。希望它是正确的。在散文中,条件仅指布尔值,前提是它可能无限期地等待,直到收到通知为止。超时基本上是第二个条件。@Dave nice,但我建议使用它的
.tryAcquire(时间,时间单位)
。如果只需要暂时阻止当前线程,请使用
thread.sleep()