wait(long timeout) in a while loop?

AFS picture AFS · Oct 24, 2012 · Viewed 13.9k times · Source

I've read that you're supposed to put Object.wait() calls in Java in a while loop. The reason is that this thread may be woken up and the condition that you were waiting to notify on is still false (spurious wake-up).

What about Object.wait(long timeout). Here, you don't want to loop on the condition since you want it to time out after the specified amount of time. But if you don't put it in a loop then how can you ensure that it won't be woken up early?

Answer

Gray picture Gray · Oct 24, 2012

But if you don't put it in a loop then how can you ensure that it won't be woken up early?

This is a deficiency in Java IMO although maybe it's a deficiency with the underlying thread support in various OS varients. I suspect Java knows whether the wait timed out or not but there is no way for the caller to figure it out without re-testing the condition and specifically testing the time. Ugly.

So you will need to put the wait(long timeout) in a while loop as well and also test to see if the time is past the timeout period. I know of no other way to accomplish this.

long timeoutExpiredMs = System.currentTimeMillis() + timeoutMs;
while (!condition) {
    long waitMillis = timeoutExpiredMs - System.currentTimeMillis();
    if (waitMillis <= 0) {
       // timeout expired
       break;
    }
    // we assume we are in a synchronized (object) here
    object.wait(waitMillis);
    // we might be improperly awoken here so we loop around to see if the
    // condition is still true or if we timed out
}