DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

How does AI transform chaos engineering from an experiment into a critical capability? Learn how to effectively operationalize the chaos.

Data quality isn't just a technical issue: It impacts an organization's compliance, operational efficiency, and customer satisfaction.

Are you a front-end or full-stack developer frustrated by front-end distractions? Learn to move forward with tooling and clear boundaries.

Developer Experience: Demand to support engineering teams has risen, and there is a shift from traditional DevOps to workflow improvements.

Related

  • Coordinating Threads Using CountDownLatch
  • Advanced Error Handling in JavaScript
  • Mastering macOS Client-Server Application Testing: Tools and Key Differences
  • Enhancing Testing Efficiency: Transitioning From Traditional Code Coverage to Code Change Coverage

Trending

  • Automating Kubernetes RBAC Sync With LDAP Entitlements Using Python
  • Software Specs 2.0: An Elaborate Example
  • Defining Effective Microservice Boundaries - A Practical Approach To Avoiding The Most Common Mistakes
  • Altering XML Tag Position Using Mule 4 With Basic Authentication
  1. DZone
  2. Data Engineering
  3. Databases
  4. Waiting for Another Thread With CountDownLatch

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.

By 
Thomas Krieger user avatar
Thomas Krieger
·
Mar. 23, 18 · Tutorial
Likes (9)
Comment
Save
Tweet
Share
17.4K Views

Join the DZone community and get the full member experience.

Join For Free

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.

Interrupt flag Task (computing) Apache Ignite Timeout (computing) Testing Blocks Signal application Clear (Unix) Google Guava

Published at DZone with permission of Thomas Krieger, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Coordinating Threads Using CountDownLatch
  • Advanced Error Handling in JavaScript
  • Mastering macOS Client-Server Application Testing: Tools and Key Differences
  • Enhancing Testing Efficiency: Transitioning From Traditional Code Coverage to Code Change Coverage

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • [email protected]

Let's be friends: