Sleep and check until condition is true

Rag picture Rag · Jan 22, 2013 · Viewed 28k times · Source

Is there a library in Java that does the following? A thread should repeatedly sleep for x milliseconds until a condition becomes true or the max time is reached.

This situation mostly occurs when a test waits for some condition to become true. The condition is influenced by another thread.

[EDIT]Just to make it clearer, I want the test to wait for only X ms before it fails. It cannot wait forever for a condition to become true. I am adding a contrived example.

class StateHolder{
    boolean active = false;
    StateHolder(){
        new Thread(new Runnable(){
            public void run(){
                active = true;
            }
        }, "State-Changer").start()
    }
    boolean isActive(){
        return active;
    }
}


class StateHolderTest{
    @Test
    public void shouldTurnActive(){
        StateHolder holder = new StateHolder();
        assertTrue(holder.isActive); // i want this call not to fail 
    }
}

Answer

assylias picture assylias · Jan 22, 2013

EDIT

Most answers focus on the low level API with waits and notifies or Conditions (which work more or less the same way): it is difficult to get right when you are not used to it. Proof: 2 of these answers don't use wait correctly.
java.util.concurrent offers you a high level API where all those intricacies have been hidden.

IMHO, there is no point using a wait/notify pattern when there is a built-in class in the concurrent package that achieves the same.


A CountDownLatch with an initial count of 1 does exactly that:

  • When the condition becomes true, call latch.countdown();
  • in your waiting thread, use : boolean ok = latch.await(1, TimeUnit.SECONDS);

Contrived example:

final CountDownLatch done = new CountDownLatch(1);

new Thread(new Runnable() {

    @Override
    public void run() {
        longProcessing();
        done.countDown();
    }
}).start();

//in your waiting thread:
boolean processingCompleteWithin1Second = done.await(1, TimeUnit.SECONDS);

Note: CountDownLatches are thread safe.