thread_CountDownLatch同步计数器

CountDownLatch类是一个同步计数器,构造时传入int参数,该参数就是计数器的初始值,每调用一次countDown()方法,计数器减1,
计数器大于0 时,await()方法会阻塞程序继续执行
 CountDownLatch如其所写,是一个倒计数的锁存器,当计数减至0时触发特定的事件。利用这种特性,可以让主线程等待子线程的结束。
1.一个模拟运动员比赛的例子 

class Player implements Runnable {
    private int id;
    private CountDownLatch begin;
    private CountDownLatch end;

    public Player(int i, CountDownLatch begin, CountDownLatch end) {
        super();
        this.id = i;
        this.begin = begin;
        this.end = end;
    }

    @Override
    public void run() {
        try {
            begin.await();                                 // 等待begin的状态为0
            Thread.sleep((long) (Math.random() * 100));    // 随机分配时间,即运动员完成时间
            System.out.println("Play" + id + " arrived.");
            
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            end.countDown();                              // 使end状态减1,最终减至0
        }
    }
}
public class CountDownLatchTest {
    private static final int PLAYER_AMOUNT = 5;

    @Test
    public void RaceTest1( ) {
        // 对于每位运动员,CountDownLatch减1后即结束比赛
        CountDownLatch begin = new CountDownLatch(1);
        
        // 对于整个比赛,所有运动员结束后才算结束
        CountDownLatch end = new CountDownLatch(PLAYER_AMOUNT);
        Player[] plays = new Player[PLAYER_AMOUNT];

        for (int i = 0; i < PLAYER_AMOUNT; i++)
            plays[i] = new Player(i + 1, begin, end);

        // 设置特定的线程池,大小为5
        ExecutorService exe = Executors.newFixedThreadPool(PLAYER_AMOUNT);
        for (Player p : plays){
            exe.execute(p);                     // 分配线程            
        }

        System.out.println("Race begins!");
        begin.countDown();
        
        try {
            end.await();                        // 等待end状态变为0,即为比赛结束
            
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            System.out.println("Race ends!");
        }
        exe.shutdown();
    }
}

2.健康检查

public class CheckHealthStartup {
    // List of service checkers
    private static List<BaseHealthChecker> _services;

    // This latch will be used to wait on
    private static CountDownLatch _latch;

    private CheckHealthStartup() {
    }

    private final static CheckHealthStartup INSTANCE = new CheckHealthStartup();

    public static CheckHealthStartup getInstance() {
        return INSTANCE;
    }

    public static boolean checkExternalServices() throws Exception {
        // Initialize the latch with number of service checkers
        _latch = new CountDownLatch(2);
        _services = new ArrayList<BaseHealthChecker>();
        // All add checker in lists

        _services.add(new NetworkHealthChecker(_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;
    }

    public static void main(String[] args) {
        boolean result = false;
        try {
            result = CheckHealthStartup.checkExternalServices();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("External services validation completed !! Result was :: " + result);
        
    }
}

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

class DatabaseHealthChecker extends BaseHealthChecker {
    public DatabaseHealthChecker(CountDownLatch latch) {
        super("Database 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");
    }
}

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();
}
原文地址:https://www.cnblogs.com/dengzy/p/5800606.html