Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 511
Rolan Avatar asked May 14 '11 00:05

Rolan


People also ask

What is CountDownLatch in Java?

CountDownLatch class is a synchronization aid which allows one or more thread to wait until the mandatory operations are performed by other threads. CountDownLatch is initialized with a given count of threads which are required to be completed before the main thread.

How do you create a wait method in Java?

wait() causes current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. In other words, this method behaves exactly as if it simply performs the call wait(0). The current thread must own this object's monitor.

When to Use wait and notify in Java?

The wait() method causes the current thread to wait until another thread invokes the notify() or notifyAll() methods for that object. The notify() method wakes up a single thread that is waiting on that object's monitor. The notifyAll() method wakes up all threads that are waiting on that object's monitor.


2 Answers

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.

like image 144
EboMike Avatar answered Oct 13 '22 05:10

EboMike


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.

like image 36
Solomon Slow Avatar answered Oct 13 '22 04:10

Solomon Slow