Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

wait(long timeout) in a while loop?

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?

like image 739
AFS Avatar asked Oct 24 '12 20:10

AFS


People also ask

How do you wait in a while loop?

The while loop contains the call to wait() . The wait() method waits indefinitely for a notification from the Producer thread. When the put() method calls notify() , the Consumer wakes up from the wait state and continues within the while loop.

Why wait is always used inside while loop?

To guarantee liveness, programs must test the while loop condition before invoking the wait() method. This early test checks whether another thread has already satisfied the condition predicate and sent a notification. Invoking the wait() method after the notification has been sent results in indefinite blocking.

Does wait method accept a timeout?

wait(long timeout) causes current thread to wait until either another thread invokes the notify() method or the notifyAll() method for this object, or a specified amount of time has elapsed.


1 Answers

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
}
like image 57
Gray Avatar answered Sep 18 '22 04:09

Gray