Multi-Programming-6 CountDown latches

1. What is CountDownLatch in java?

这里将得到关于该问题的详细信息。

CountDownLatch in Java is a type of synchronizer which allows one
Thread to wait for one or more Threads before it starts processing.

CountDownLatch works on latch principle, thread will wait until gate
is open. One thread waits for n number of threads specified while
creating CountDownLatch.

e.g. final CountDownLatch latch = new CountDownLatch(3);

Here we set the counter to 3.

Any thread, usually main thread of application, which calls
CountDownLatch.await() will wait until count reaches zero or it’s
interrupted by another Thread. All other threads are required to do
count down by calling CountDownLatch.countDown() once they are
completed or ready to the job. as soon as count reaches zero, the
Thread awaiting starts running.

Here the count is get decremented by CountDownLatch.countDown()
method.

The Thread which calls the await() method will wait until the initial
count reaches to zero.

To make count zero other threads need to call the countDown() method.
Once the count become zero the thread which invoked the await() method
will resume (start its execution).

The disadvantage of CountDownLatch is that it’s not reusable: once the
count become zero it is no longer usable.
CountDownLatch是一种同步机制,使得一个线程在开始执行之前等待一个或多个线程完成。

2. How is it used?

latch.countDown():每次线程执行完后,latch值减1.
latch.await():等待latch的值变为0.
一般调用latch.await()的线程(一般是主线程)将会一直等待,直到latch数量为0,或被中断。

3. Example-1

package com.fqyuan.blog;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class LatchDemo {

    public static void main(String[] args) {
        LatchDemoUtil.demonstrate();
    }

}

class LatchDemoUtil {
    public static void demonstrate() {
        long startTime = System.currentTimeMillis();
        CountDownLatch latch = new CountDownLatch(5);
        ExecutorService executor = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 5; i++) {
            executor.submit(new TaskWithLatch(latch));
        }
        try {
            latch.await();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("Time taken is: " + (endTime - startTime));
    }
}

class TaskWithLatch implements Runnable {
    private CountDownLatch latch;

    public TaskWithLatch(CountDownLatch latch) {
        this.latch = latch;
    }

    private void process() {
        System.out.println("Starting...");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        latch.countDown();
        System.out.println("Ending...");
    }

    @Override
    public void run() {
        process();
    }
}
运行结果:
Starting...
Starting...
Starting...
Ending...
Ending...
Ending...
Starting...
Starting...
Ending...
Ending...
Time taken is: 2010

4. Example-2

代码有点长,主要是模拟一种系统检查,当所有项目检查都正常通过时,主程序输出结果。

package com.fqyuan.blog;

import java.util.concurrent.CountDownLatch;

public abstract class BaseHealthChecker implements Runnable {
    private String name;
    private CountDownLatch latch;
    private boolean isServiceUp;

    public BaseHealthChecker(String name, CountDownLatch latch) {
        this.name = name;
        this.latch = latch;
        isServiceUp = false;
    }

    public String getName() {
        return name;
    }

    public boolean isServiceUp() {
        return isServiceUp;
    }

    @Override
    public void run() {
        try {
            verifyService();
            isServiceUp = true;
        } catch (Throwable t) {
            isServiceUp = false;
            t.printStackTrace(System.err);
        } finally {
            if (latch != null)
                latch.countDown();
        }
    }

    public abstract void verifyService();

}
package com.fqyuan.blog;

import java.util.concurrent.CountDownLatch;

public class CacheServiceChecker extends BaseHealthChecker {
    public CacheServiceChecker(CountDownLatch latch) {
        super("Cache Service", latch);
    }

    @Override
    public void verifyService() {
        System.out.println("Checking " + this.getName());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(this.getName() + " is up.");
    }
}
package com.fqyuan.blog;

import java.util.concurrent.CountDownLatch;

public class DatabaseServiceChecker extends BaseHealthChecker {

    public DatabaseServiceChecker(CountDownLatch latch) {
        super("Database service", latch);
    }

    @Override
    public void verifyService() {
        System.out.println("Checking " + this.getName());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(this.getName() + " is up.");
    }

}
package com.fqyuan.blog;

import java.util.concurrent.CountDownLatch;

public class NetServiceChecker extends BaseHealthChecker {
    public NetServiceChecker(CountDownLatch latch) {
        super("Network service", latch);
    }

    @Override
    public void verifyService() {
        System.out.println("Checking " + this.getName());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(this.getName() + " is up.");
    }

}
package com.fqyuan.blog;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class LatchUtil {
    private static CountDownLatch latch;
    private static List<BaseHealthChecker> list;
    private static final LatchUtil INSTANCE = new LatchUtil();

    // Singleton pattern
    private LatchUtil() {

    }

    public static LatchUtil getInstance() {
        return INSTANCE;
    }

    public static boolean isServicesReady() {
        list = new ArrayList<>();
        latch = new CountDownLatch(3);
        ExecutorService executor = Executors.newFixedThreadPool(3);

        list.add(new NetServiceChecker(latch));
        list.add(new CacheServiceChecker(latch));
        list.add(new DatabaseServiceChecker(latch));
        for (BaseHealthChecker checker : list)
            executor.submit(checker);
        executor.shutdown();
        try {
            executor.awaitTermination(1, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        for (BaseHealthChecker checker : list) {
            if (checker.isServiceUp() == false)
                return false;
        }
        return true;
    }
}
package com.fqyuan.blog;

public class Main {

    public static void main(String[] args) {
        boolean flag = LatchUtil.isServicesReady();
        System.out.println("Checking result is: " + flag);
    }

}

运行结果:

Checking Cache Service
Checking Database service
Checking Network service
Network service is up.
Database service is up.
Cache Service is up.
Checking result is: true

You may follow me @github����.

你可能感兴趣的:(java,线程)