Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Waiting for Another Thread With CountDownLatch

DZone's Guide to

Waiting for Another Thread With CountDownLatch

See how you make the best use of CountDownLatch to wait for threads with these two real-life examples regarding initialization and testing multithreaded software.

· Java Zone ·
Free Resource

Get the Edge with a Professional Java IDE. 30-day free trial.

CountDownLatch is an easy way to wait until another thread has finished a task. The CountDownLatch is initialized by the number of threads we need to wait for. After a thread has finished its task, it calls countDown, counting down the countdown. A thread can wait until the countdown reaches zero by calling await. We will see how to use it by looking at two real-life examples.

How to Use CountDownLatch: Waiting for Initialization

The Apache Ignite CacheDataStructuresManager needs to wait until it is initialized. One thread initializes the CacheDataStructuresManager, so we need a CountDownLatch with count one:

private final CountDownLatch initLatch = new CountDownLatch(1);


The initialization is done in the onKernalStart0() method:

@Override protected void onKernalStart0() 
                    throws IgniteCheckedException {
    try {
        queueHdrView = cctx.cache();
        initFlag = true;
    }
    finally {
        initLatch.countDown();
    }
}


The countDown method is called in the finally block, so we guarantee that the countdown eventually reaches zero and we do not wait forever. To signal that the initialization was successful, we use the boolean flag initFlag.

The method waitInitialization is used to check if the initialization was successful:

private void waitInitialization() 
         throws IgniteCheckedException {
    if (initLatch.getCount() > 0)
        U.await(initLatch);
    if (!initFlag)
        throw new IgniteCheckedException(
           "DataStructures manager was not properly initialized.");
}


We check the count of the CountDownLatch, waiting if necessary in the await method from IgniteUtils. After that, we check the initFlag if the initialization was successful.

The method await from IgniteUtils handles the InterruptedException from the CountDownLatch await method:

public static void await(CountDownLatch latch) 
              throws IgniteInterruptedCheckedException {
    try {
        if (latch.getCount() > 0)
            latch.await();
    }
    catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        throw new IgniteInterruptedCheckedException(e);
    }
}


In the example, the interrupt flag is restored by calling Thread.currentThread().interrupt() and a new checked Exception is thrown.

Handling of InterruptedException

The await method of the CountDownLatch throws an InterruptedException when the method Thread.interrupt was called. The CountDownLatch clears the interrupt flag when it throws the InterruptedException. Therefore, the book Java Concurrency in Practice - Brian Goetz, et al. recommends to either propagate the InterruptedException or to restore the interrupt flag.

The Guava library provides the utility method, awaitUninterruptibly, in the class Uninterruptibles, which implements the second recommendation. It restores the interrupt flag. Using this method, you make sure that another blocking method will again throw an InterruptedException.

How to Use Await With a Timeout: Testing Multithreaded Software

The next example shows how to call the second method to wait for other threads, await with a timeout: This method is typically used in tests, like in this example in the PostServletTest from jetty:

@Test
public void testBadPost() throws Exception
{
    StringBuilder req = new StringBuilder(16*1024);
    // creation of the request String omitted
    String resp = connector.getResponse(req.toString());
    assertThat(resp,startsWith("HTTP/1.1 200 OK")); 
    assertTrue(complete.await(5,TimeUnit.SECONDS));
    assertThat(ex0.get(),not(nullValue()));
    assertThat(ex1.get(),not(nullValue()));
}


The await method gets called with the amount we want to wait, together with the unit for the amount, line 8. In our example, we want to wait no more than 5 seconds. The test fails when the await method returns false because of the timeout.

Summary and Next Steps

When you want to wait for another thread with CountDownLatch follow these steps:

  1. Initialize the CountDownLatch with the number of threads you are waiting for.
  2. Call the countDown method in the finally block when a thread has finished its task.
  3. Use a flag or counter to signal that the tasks were successful.
  4. Wait for the threads with the method await. Propagate the InterruptedException thrown by await or restore the interrupted flag when you catch the InterruptedException.

The CountDownLatch can only be used once. We will look at the CyclicBarrier next, which can be used multiple times. I would be glad to hear from you about how you use CountDownLatch in your application.

Get the Java IDE that understands code & makes developing enjoyable. Level up your code with IntelliJ IDEA. Download the free trial.

Topics:
concurrent programming ,countdownlatch ,java ,initialization ,tutorial

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}