CountDownLatch provides a means of waiting for a number of asynchronous events before proceeding. In order to do this one constructs a latch providing the event count. Then one thread would normally call await W
hilst the other thread calls countDown
. Once the count reaches zero the await
call returns and the latch is set. If the call to await
happens after the latch is set it returns immediately.
In our example we need to wait for a thread to initialise before proceeding. We achieve this by creating a count down latch with a count of 1. Once the thread has done its work, it calls countDown on the latch. In the mean time the main thread has continued to do its longJob and then called await on the CountDownLatch instance. Calling await blocks until countDown has been called enough times (in this case once).
package com.thecoderscorner.example;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This example demonstrates a very simple usage of CountDownLatch.
* It requires a Java 8 compiler.
*/
public class CountDownLatchExample {
private final static Logger LOG = Logger.getLogger("TEST");
public static void main(String[] args) throws InterruptedException {
// create a latch that will wait for 1 countdown call.
CountDownLatch latch = new CountDownLatch(1);
// create and start the thread that we have to wait for.
new Thread(() -> {
// simulate some tasks.
try {
Thread.sleep(100);
} catch (InterruptedException e) {
LOG.log(Level.SEVERE, "Exception while waiting", e);
// no need to re set the interrupt flag, we are exiting now!
}
LOG.info("Before latch is counted down");
latch.countDown();
}).start();
// perform the jobs on the main thread.
LOG.info("Before await");
// then await the latch, this is often very useful when testing,
// because we can wait for something to happen elsewhere before
// proceeding. If we set a time out we know the test would fail
// if the latch was never triggered.
if(latch.await(5, TimeUnit.SECONDS)) {
LOG.info("Returned from await");
}
else {
// if you want to test this flow, just comment out the
// start() call on the thread.
LOG.info("Failed to return from wait, timed out");
}
}
}
And here is the output for the above example:
May 10, 2015 7:28:26 AM com.thecoderscorner.example.CountDownLatchExample main
INFO: Before await
May 10, 2015 7:28:26 AM com.thecoderscorner.example.CountDownLatchExample lambda$main$0
INFO: Before latch is counted down
May 10, 2015 7:28:26 AM com.thecoderscorner.example.CountDownLatchExample main
INFO: Returned from await
Process finished with exit code 0