Simple Explanation of Count-Down Latch working (with code example)

CountDown Latch is another important topic in multi-threading in Java which is often asked in Java interviews. Why?

Because of the way it works and the cases in which it should be applied.

A count-down latch is like a door-latch, a door-latch applied on the door will not let anyone go through it but will block the person. But, once it is opened, the blocked person can go through the door. The only point is that once the latch's value is 0, then it cannot be incremented again, where Cyclic barrier comes into picture. I will post another article on that as well.

It is used mostly for setting up the system initially, ex - in many gaming platforms where lets say 5 persons need to play a game and unless all 5 have not joined, the game cannot proceed further. So, we can apply CountDownLatch there.

The concept is simple, the 'calling' thread which needs to wait for others to finish as to call await method on latch object to simplify that it is waiting to achieve for a number of threads to finish. Once each 'called' thread finished, it calls countdown method on the latch object to signify to the calling thread that the thread is returned and successfully finished processing.

In the below example, there is a system-setup thread, a main thread and a worker thread. The application flow is:

Main thread starts a system setup thread and awaits on a latch object to become 0 from 1 i.e. it waits for one called thread to return. The called thread here is the system-setup thread. Once system setup thread returns by setting up the system in a number of different ways, main thread starts a worker thread which will do all the processing the application is supposed to do after the system is setup. Main thread will wait for worker thread since worker thread calls join on the main thread. After the worker thread is finished executing the main thread can now clear the system resources acquired by the application and can gracefully shutdown.

import java.util.concurrent.CountDownLatch;

public class TestADiscreteTransaction
{
    private static final CountDownLatch latch = new CountDownLatch(1);
    public static void main(String[] args)
    {
        Thread thread = new Thread(new InitialSetupTheSystemThread());
        thread.start();
        try
        {
            System.out.println("Setting Up the System now");
            latch.await();
            System.out.println("System has been setup successfully. Now, proceeding with the application");
            // Create the worker thread. You can implement scheduling here as well. And, create different worker threads.
            WorkerThread worker = new WorkerThread();
            System.out.println("Starting Worker Thread");
            worker.start();
            System.out.println("Worker Thread started");

            //pause execution of main thread.
            worker.join();
            System.out.println("Worker Thread finished executing");
            System.out.println("Main Thread Resuming... ");
            
            System.out.println("Clear resources");
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
                System.err.println("The latch has been interrupted");
            }
        }
    
        private static class InitialSetupTheSystemThread implements Runnable
        {
            @Override public void run()
            {
                try
                {
                    setupInitialSystem();
                    latch.countDown();
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                    System.err.println("Could not setup the system. Exiting!!");
                }
            }
    
            private void setupInitialSystem() throws Exception
            {
                setUpEnvironment();
                setUpLogging();
                setUpDBConnectionSingleton();
                setupKafkaStreams();
                setUpKafkaStreamMetrics();
                setUpMessageQueues();
                setupApplicationMonitoringMetrics();
                setUpOthers();
            }
    
            // Exception is shown only to signify that if there is any exception raised, that means a particular step
            // could not be setup and there is an error at the start which means that the system cannot proceed further.
            private void setUpOthers() throws Exception
            {
                System.out.println("Setting up -Others-");
                Thread.sleep(1000);
            }
    
            private void setupApplicationMonitoringMetrics() throws Exception
            {
                System.out.println("Setting up ApplicationMonitoringMetrics");
                Thread.sleep(1000);
            }
    
            private void setUpMessageQueues() throws Exception
            {
                System.out.println("Setting up MessageQueues");
                Thread.sleep(1000);
            }

        private void setUpKafkaStreamMetrics() throws Exception
        {
            System.out.println("Setting up KafkaStreamMetrics");
            Thread.sleep(1000);
        }

        private void setupKafkaStreams() throws Exception
        {
            System.out.println("Setting up KafkaStreams");
            Thread.sleep(1000);
        }

        private void setUpDBConnectionSingleton() throws Exception
        {
            System.out.println("Setting up DBConnectionSingleton");
            Thread.sleep(1000);
        }

        private void setUpLogging() throws Exception
        {
            System.out.println("Setting up Logging");
            Thread.sleep(1000);
        }

        private void setUpEnvironment() throws Exception
        {
            System.out.println("Setting up Environment");
            Thread.sleep(1000);
        }
    }

    private static class WorkerThread extends Thread
    {
        @Override
        public void run()
        {
            System.out.println("Welcome from Worker Thread. From here on, I will work and do "
                    + " all the work or get the work done by my friends. many thanks to the System Setup thread "
                    + "for setting the system up for me.");
            try
            {
                Thread.sleep(5000);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
                System.err.println("Worker thread is interrrupted");
            }
        }
    }
}        

If you like my content, please give me a thumbs-up. Also, stay-tuned for more content with simple and code-based explanations along-with real-world use-cases.

To view or add a comment, sign in

More articles by Ashish Kumar Singh

Explore content categories