How CountDownLatch work?

As every Java document described as, CountDownLatch class is a synchronization tool that allows one or more threads waits until the execution of the operation of the other threads finish before execution. Concurrency in Java, the concept countdownlatch is a common interview questions, so make sure you have a good understanding of it. In this article, I will be involved in the following Java concurrent programming associated with CountDownLatch of:

table of Contents

  • What CountDownLatch that?
  • How CountDownLatch work?
  • Scenarios in real-time systems
  • Application Examples

What is CountDownLatch

CountDownLatch is introduced in java1.5, saying complicated tools there CyclicBarrier, Semaphore, introduced together ConcurrentHashMap and BlockingQueue , which are present in the java.util.concurrent package. CountDownLatch This class enables a thread waiting for other threads to complete their work before execution. For example, the application's main thread of hope again after the thread is responsible for starting the implementation of the framework service has been launched in the framework of all the services.

CountDownLatch number is achieved by a counter, the initial value of the thread counter. Whenever a thread after the completion of its mandate, the counter will be decremented by one. When the counter value reaches zero, it means that all the threads have completed the task, and then wait for the thread locking can be restored on a mission.

CountDownLatch.java class constructor is defined:

The constructor of the count value (count) is actually blocking the number of threads to wait . This value can be set only once, and CountDownLatch does not provide any mechanism to reset the count value .

The first and CountDownLatch interaction is the main thread to wait for another thread. The main thread must be called immediately after starting another thread CountDownLatch.await () method. Such operations will be the main thread on this method blocks until another thread to complete their task.

Other N threads must refer blocking objects, because they need to notify CountDownLatch objects, they have completed their tasks. Such notification mechanism by  CountDownLatch.countDown () to accomplish the method; this method once for each call to initialize the count value in the constructor decrements. So when the N threads call this method, the value of count is equal to 0, then the main thread can pass await () method, resumption of their task.

In the real-time system usage scenarios

Let's try to set out in a real-time system java CountDownLatch What are usage scenarios. I have listed all I can think of. If you have another possible use, please be listed in the message, this will help to you.

  1. For maximum parallelism : Sometimes we want to start multiple threads to achieve the greatest degree of parallelism. For example, we want to test a singleton class. If we create an initial count of CountDownLatch 1, and to let all threads waiting on the lock, then we can easily complete the test. We just call once countDown () method can make all the waiting threads resume execution.
  2. N threads waiting to complete their tasks before starting : the application starts, for example, to ensure that the class before processing user requests, all of the N external system has been up and running.
  3. Deadlock detection: a scenario is very convenient to use, you can use the n threads to access shared resources, the number of threads in each test phase is different, and try to deadlock.

Examples of use CountDownLatch

In this example, I simulate an application startup class, which started at the beginning of class n threads, these threads will check the external system and notify the lockout and start the class has been waiting on the lockout. Once verified and checked all external service, then start classes resume execution.

BaseHealthChecker.java: This class is a Runnable, responsible for all specific external service health testing. It deletes duplicate code and locking the central control code.

 

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 inherits BaseHealthChecker, realized verifyService () method. DatabaseHealthChecker.java and CacheHealthChecker.java In addition to the service name and the sleep time, and NetworkHealthChecker.java is the same.

 

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 class is a class master boot, it is responsible for initializing the latch, and then wait until all the services are completely detected.

 

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 test code to detect what the function of a lockout.

 

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);
    }
}

Guess you like

Origin blog.csdn.net/bj_chengrong/article/details/83344897