Java concurrency – CountDownLatch Example

https://howtodoinjava.com/java/multi-threading/when-to-use-countdownlatch-java-concurrency-example-tutorial/

As per java docs, CountDownLatch is a synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes. CountDownLatch concept is very common interview question in java concurrency, so make sure you understand it well. In this post, I will cover following points related to CountDownLatch in java concurrency.

Sections in this post:

What is CountDownLatch?
How CountDownLatch works?
Possible usages in real time applications
Example application
Common interview questions

What is CountDownLatch?

CountDownLatch was introduced with JDK 1.5 along with other concurrent utilities like CyclicBarrier, Semaphore, ConcurrentHashMap and BlockingQueue in java.util.concurrent package. This class enables a java thread to wait until other set of threads completes their tasks. e.g. Application’s main thread want to wait, till other service threads which are responsible for starting framework services have completed started all services.

CountDownLatch works by having a counter initialized with number of threads, which is decremented each time a thread complete its execution. When count reaches to zero, it means all threads have completed their execution, and thread waiting on latch resume the execution.

CountdownLatchCountDownLatch Concept

Pseudo code for CountDownLatch can be written like this:

//Main thread start
//Create CountDownLatch for N threads
//Create and start N threads
//Main thread wait on latch
//N threads completes there tasks are returns
//Main thread resume execution

How CountDownLatch works?

CountDownLatch.java class defines one constructor inside:

//Constructs a CountDownLatch initialized with the given count.
public  CountDownLatch( int  count) {...}

This count is essentially the number of threads, for which latch should wait. This value can be set only once, and CountDownLatch provides no other mechanism to reset this count.

The first interaction with CountDownLatch is with main thread which is goind to wait for other threads. This main thread must call, CountDownLatch.await() method immediately after starting other threads. The execution will stop on await() method till the time, other threads complete their execution.

Other N threads must have reference of latch object, because they will need to notify the CountDownLatch object that they have completed their task. This notification is done by method : CountDownLatch.countDown(); Each invocation of method decreases the initial count set in constructor, by 1. So, when all N threads have call this method, count reaches to zero, and main thread is allowed to resume its execution past await() method.

Possible usages in real time applications

Let’s try to identify some possible usage of CountDownLatch in real time java applications. I am listing, as much i can recall. If you have any other possible usage, please leave a comment. It will help others.

  1. Achieving Maximum Parallelism : Sometimes we want to start a number of threads at the same time to achieve maximum parallelism. For example, we want to test a class for being singleton. This can be done easily if we create a CountDownLatch with initial count 1, and make wait all threads to wait of latch. A single call to countDown() method will resume execution for all waiting threads in same time.
  2. Wait N threads to completes before start execution: For example an application start-up class want to ensure that all N external systems are Up and running before handling the user requests.
  3. Deadlock detection: A very handy use case in which you can use N threads to access a shared resource with different number of threads in each test phase, and try to create a deadlock.

Example application using CountDownLatch

In this example, I have simulated an application startup class which starts N threads that will check for external systems and report back to latch, on which startup class is waiting. As soon as all services are verified and checked, startup proceeds.

BaseHealthChecker.java : This class is a Runnable and parent for all specific external service health checkers. This remove the code duplicacy and central control over latch.

public  abstract  class  BaseHealthChecker  implements  Runnable {
     
     private  CountDownLatch _latch;
     private  String _serviceName;
     private  boolean  _serviceUp;
     
     //Get latch object in constructor so that after completing the task, thread can countDown() the latch
     public  BaseHealthChecker(String serviceName, CountDownLatch latch)
     {
         super ();
         this ._latch = latch;
         this ._serviceName = serviceName;
         this ._serviceUp =  false ;
     }
 
     @Override
     public  void  run() {
         try  {
             verifyService();
             _serviceUp =  true ;
         catch  (Throwable t) {
             t.printStackTrace(System.err);
             _serviceUp =  false ;
         finally  {
             if (_latch !=  null ) {
                 _latch.countDown();
             }
         }
     }
 
     public  String getServiceName() {
         return  _serviceName;
     }
 
     public  boolean  isServiceUp() {
         return  _serviceUp;
     }
     //This methos needs to be implemented by all specific service checker
     public  abstract  void  verifyService();
}

NetworkHealthChecker.java : This class extends BaseHealthChecker and needs to provide only implementation of verifyService() method. DatabaseHealthChecker.java and CacheHealthChecker.java are same as NetworkHealthChecker.java apart from their service names and sleep time.

public  class  NetworkHealthChecker  extends  BaseHealthChecker
{
     public  NetworkHealthChecker (CountDownLatch latch)  {
         super ( "Network Service" , latch);
     }
     
     @Override
     public  void  verifyService()
     {
         System.out.println( "Checking "  this .getServiceName());
         try
         {
             Thread.sleep( 7000 );
         }
         catch  (InterruptedException e)
         {
             e.printStackTrace();
         }
         System.out.println( this .getServiceName() +  " is UP" );
     }
}

ApplicationStartupUtil.java : This clas is main startup class which initilizes the latch and wait of this latch till all services are checked.

public  class  ApplicationStartupUtil
{
     //List of service checkers
     private  static  List<BaseHealthChecker> _services;
     
     //This latch will be used to wait on
     private  static  CountDownLatch _latch;
     
     private  ApplicationStartupUtil()
     {
     }
     
     private  final  static  ApplicationStartupUtil INSTANCE =  new  ApplicationStartupUtil();
     
     public  static  ApplicationStartupUtil getInstance()
     {
         return  INSTANCE;
     }
     
     public  static  boolean  checkExternalServices()  throws  Exception
     {
         //Initialize the latch with number of service checkers
         _latch =  new  CountDownLatch( 3 );
         
         //All add checker in lists
         _services =  new  ArrayList<BaseHealthChecker>();
         _services.add( new  NetworkHealthChecker(_latch));
         _services.add( new  CacheHealthChecker(_latch));
         _services.add( new  DatabaseHealthChecker(_latch));
         
         //Start service checkers using executor framework
         Executor executor = Executors.newFixedThreadPool(_services.size());
         
         for ( final  BaseHealthChecker v : _services)
         {
             executor.execute(v);
         }
         
         //Now wait till all services are checked
         _latch.await();
         
         //Services are file and now proceed startup
         for ( final  BaseHealthChecker v : _services)
         {
             if ( ! v.isServiceUp())
             {
                 return  false ;
             }
         }
         return  true ;
     }
}

Now you can write any test class to check the functionality of latch.

public  class  Main {
     public  static  void  main(String[] args)
     {
         boolean  result =  false ;
         try  {
             result = ApplicationStartupUtil.checkExternalServices();
         catch  (Exception e) {
             e.printStackTrace();
         }
         System.out.println( "External services validation completed !! Result was :: " + result);
     }
}
 
Output in console:
 
Checking Network Service
Checking Cache Service
Checking Database Service
Database Service is UP
Cache Service is UP
Network Service is UP
External services validation completed !! Result was ::  true

Common interview questions

Be prepared to face these questions related to CountDownLatch in your next interview.

  • Explain the concept of CountDownLatch?
  • Difference between CountDownLatch and CyclicBarrier?
  • Give some example uses of CountDownLatch?
  • What are main methods CountDownLatch class has?

To Download the sourcecode of above example application follow given link.

Sourcecode Download

转载于:https://www.cnblogs.com/davidwang456/articles/10213365.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值