55

I have a thread which wait for a boolean value to change like this:

while(!value)
{
  Thread.sleep(1000)
}
// Do some work after change of the value

This is not my prefered way to do this, cause of massive CPU consumption.

Is there any way to block the Thread, until the boolean value changes it state?

marc3l
  • 2,449
  • 7
  • 33
  • 58

6 Answers6

87

This is not my prefered way to do this, cause of massive CPU consumption.

If that is actually your working code, then just keep it like that. Checking a boolean once a second causes NO measurable CPU load. None whatsoever.

The real problem is that the thread that checks the value may not see a change that has happened for an arbitrarily long time due to caching. To ensure that the value is always synchronized between threads, you need to put the volatile keyword in the variable definition, i.e.

private volatile boolean value;

Note that putting the access in a synchronized block, such as when using the notification-based solution described in other answers, will have the same effect.

Michael Borgwardt
  • 335,521
  • 76
  • 467
  • 706
59

You need a mechanism which avoids busy-waiting. The old wait/notify mechanism is fraught with pitfalls so prefer something from the java.util.concurrent library, for example the CountDownLatch:

public final CountDownLatch latch = new CountDownLatch(1);

public void run () {
  latch.await();
  ...
}

And at the other side call

yourRunnableObj.latch.countDown();

However, starting a thread to do nothing but wait until it is needed is still not the best way to go. You could also employ an ExecutorService to which you submit as a task the work which must be done when the condition is met.

t0r0X
  • 3,595
  • 1
  • 31
  • 30
Marko Topolnik
  • 188,298
  • 27
  • 302
  • 416
  • This helps me for testing the Quartz library inside of JUnit. Quartz runs its jobs in a blackbox that has its own thread pool. I can signal JUnit to wait for the quartz jobs to complete using the exact pattern specified in the java doc. – David Mann Jan 02 '14 at 20:16
  • 2
    Can I suggest the `Java.util.concurrent.BlockingQueue` and its various implementations? The `take()` and `offer()` methods are a great starting place for synchronization. – Groostav Jan 06 '16 at 23:20
8

How about wait-notify

private Boolean bool = true;
private final Object lock = new Object();

private Boolean getChange(){
  synchronized(lock){
    while (bool) {
      bool.wait();
    }
   }
  return bool;
}
public void setChange(){
   synchronized(lock){
       bool = false;
       bool.notify();
   }
}
Subhrajyoti Majumder
  • 39,719
  • 12
  • 74
  • 101
2

Ok maybe this one should solve your problem. Note that each time you make a change you call the change() method that releases the wait.

Integer any = new Integer(0);

public synchronized boolean waitTillChange() {
    any.wait();
    return true;
}

public synchronized void change() {
    any.notify();
}
luiso1979
  • 881
  • 1
  • 6
  • 18
0

I prefer to use mutex mechanism in such cases, but if you really want to use boolean, then you should declare it as volatile (to provide the change visibility across threads) and just run the body-less cycle with that boolean as a condition :

//.....some class

volatile boolean someBoolean; 

Thread someThread = new Thread() {

    @Override 
    public void run() {
        //some actions
        while (!someBoolean); //wait for condition 
        //some actions 
    }

};
0
public Boolean test() throws InterruptedException {
    BlockingQueue<Boolean> booleanHolder = new LinkedBlockingQueue<>();
    new Thread(() -> {
        try {
            TimeUnit.SECONDS.sleep(2);
            booleanHolder.put(true);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }).start();
    return booleanHolder.poll(4, TimeUnit.SECONDS);
}
kreker
  • 5,713
  • 5
  • 39
  • 33