is there a 'block until condition becomes true' function in java?

I'm writing a listener thread for a server, and at the moment I'm using:

while (true){
    try {
        if (condition){
            //do something
            condition=false;
        }
        sleep(1000);

    } catch (InterruptedException ex){
        Logger.getLogger(server.class.getName()).log(Level.SEVERE, null, ex);
    }
}

With the code above, I'm running into issues with the run function eating all the cpu time looping. The sleep function works, but it seems be a makeshift fix, not a solution.

Is there some function which would block until the variable 'condition' became 'true'? Or is continual looping the standard method of waiting until a variable's value changes?


Polling like this is definitely the least preferred solution.

I assume that you have another thread that will do something to make the condition true. There are several ways to synchronize threads. The easiest one in your case would be a notification via an Object:

Main thread:

synchronized(syncObject) {
    try {
        // Calling wait() will block this thread until another thread
        // calls notify() on the object.
        syncObject.wait();
    } catch (InterruptedException e) {
        // Happens if someone interrupts your thread.
    }
}

Other thread:

// Do something
// If the condition is true, do the following:
synchronized(syncObject) {
    syncObject.notify();
}

syncObject itself can be a simple Object.

There are many other ways of inter-thread communication, but which one to use depends on what precisely you're doing.


EboMike's answer and Toby's answer are both on the right track, but they both contain a fatal flaw. The flaw is called lost notification.

The problem is, if a thread calls foo.notify(), it will not do anything at all unless some other thread is already sleeping in a foo.wait() call. The object, foo, does not remember that it was notified.

There's a reason why you aren't allowed to call foo.wait() or foo.notify() unless the thread is synchronized on foo. It's because the only way to avoid lost notification is to protect the condition with a mutex. When it's done right, it looks like this:

Consumer thread:

try {
    synchronized(foo) {
        while(! conditionIsTrue()) {
            foo.wait();
        }
        doSomethingThatRequiresConditionToBeTrue();
    }
} catch (InterruptedException e) {
    handleInterruption();
}

Producer thread:

synchronized(foo) {
    doSomethingThatMakesConditionTrue();
    foo.notify();
}

The code that changes the condition and the code that checks the condition is all synchronized on the same object, and the consumer thread explicitly tests the condition before it waits. There is no way for the consumer to miss the notification and end up stuck forever in a wait() call when the condition is already true.

Also note that the wait() is in a loop. That's because, in the general case, by the time the consumer re-acquires the foo lock and wakes up, some other thread might have made the condition false again. Even if that's not possible in your program, what is possible, in some operating systems, is for foo.wait() to return even when foo.notify() has not been called. That's called a spurious wakeup, and it is allowed to happen because it makes wait/notify easier to implement on certain operating systems.