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

时间:2016-04-01 18:12:49

标签: java concurrency

我已经了解到,在等待一个对象时,条件应该放在一个循环中而不是在一个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条件!

这是如何解决的?

2 个答案:

答案 0 :(得分:2)

这是我通常如何处理这个问题:

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

答案 1 :(得分:1)

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

synchronized (obj) {
    for (long time = System.currentTimeMillis() + timeout; !condition && System.currentTimeMillis() < time; ) {
        obj.wait(time - System.currentTimeMillis());
    }
    if (condition) {
        ... do something ...
    }
}