11

Here is a case where a thread is waiting for notify() or a timeout. Here a while loop is added to handle spurious wake up.

boolean dosleep = true;
while (dosleep){
    try {
        wait(2000);
        /**
         * Write some code here so that
         * if it is spurious wakeup, go back and sleep.
         * or if it is timeout, get out of the loop. 
         */

    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

In this case how can I distinguish between a spurious wake up and time out? If it is a spurious wake up, i need to go back and wait. And if it is a timeout, i need to get out of the loop.

I can easily identify the case of notify(), because i will be setting the dosleep variable to false while notify() call.

EDIT: i am using 1.4 java version, due to embedded project requirement. I cannot use Condition as it is available only post 1.5.

Thanks in advance.

M S
  • 3,995
  • 3
  • 25
  • 36
  • Bringer128 has a reasonable solution, but, I question why you want to do this. The Interrupt is generally not a "spurious wakeup", it is a signal to interrupt and _stop_ the process. – user949300 Nov 18 '11 at 06:46
  • Its not about interrupt. A "spurious wakeup" can come at any time. If it comes in the same time after I enter to the wait(), i dont want to get out of the loop then. I need to asure that i wait atlease `timeout` time before i exit the loop – M S Nov 18 '11 at 07:03
  • I see. You aren't getting interrupted, but some other thread is calling notify() or, more likely, notifyAll(), and you get woken up. – user949300 Nov 18 '11 at 17:56
  • see also http://stackoverflow.com/questions/3397722/how-to-differentiate-when-waitlong-timeout-exit-for-notify-or-timeout – Hernán Eche Jul 23 '13 at 20:51

3 Answers3

9

You could do this:

boolean dosleep = true;
long endTime = System.currentTimeMillis() + 2000;
while (dosleep) {
    try {
        long sleepTime = endTime - System.currentTimeMillis();
        if (sleepTime <= 0) {
            dosleep = false;
            } else {
            wait(sleepTime);
        }
    } catch ...
}

That should work fine in Java 1.4, and it will ensure that your thread sleeps for at least 2000ms.

Cameron Skinner
  • 51,692
  • 2
  • 65
  • 86
6

You need to keep track of your timeout if you want to distinguish the two cases.

long timeout = 2000;
long timeoutExpires = System.currentTimeMillis() + timeout;
while(dosleep) {
  wait(timeout);
  if(System.currentTimeMillis() >= timeoutExpires) {
    // Get out of loop
    break;
  }
}

That said, denis's recommendation of using the Condition class is the better way to do this.

  • This code waits again for the whole timeout after the spurious wakeup has occurred and that is not correct. Cameron Skinner's response is correct and is also backward compatible with JDK v4 (while Denis.Solonenko's answer is also correct, it uses the `java.concurrency` API and, thus, needs JDK v5+). That is my bit to the topic. – Jiri Patera Jan 25 '12 at 14:33
  • 3
    Don't use System.currentTimeMillis() use some form of monotonic time instead since this is prone to misbehave when the system clock is changed. http://stackoverflow.com/questions/351565/system-currenttimemillis-vs-system-nanotime – Eric des Courtis Jun 21 '13 at 02:04
  • As Jiri Patera has pointed out, the example is flawed in itself. Moreover, besides the "Condition class" actually being an interface, the JavaDoc of [Condition](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Condition.html) clearly says that `An implementation is free to remove the possibility of spurious wakeups but it is recommended that applications programmers always assume that they can occur and so always wait in a loop`. Cameron Skinner has the only right answer. – Martin Andersson Mar 09 '14 at 16:33
4

I believe Locks and Condition will better fit your need in this case. Please check the javadocs for Condition.awaitUntil() - it has an example of usage

denis.solonenko
  • 11,645
  • 2
  • 28
  • 23
  • 1
    i am using 1.4 java version, due to embedded project requirement. I am afraid that Condition is available only post 1.5. – M S Nov 18 '11 at 06:23