简介
CountDownLatch也叫闭锁,它是J.U.C包中基于AQS共享锁实现的一个很简单的类,它允许一个或多个线程等待其他线程完成操作后再执行。
CountDownLatch内部会维护一个资源数量为初始化值为的计数器,当A线程调用await方法后,A线程会在计数器大于0的时候一直阻塞等待。当一个线程完成任务后,计数器的值会减1。当计数器变为0时,表示所有的线程已经完成任务,等待的主线程被唤醒继续执行。
源码分析
protected int tryAcquireShared(int acquires) { //资源等于-1时阻塞等待 return (getState() == 0) ? 1 : -1;}protected boolean tryReleaseShared(int releases) { for (;;) { int c = getState(); if (c == 0) return false; int nextc = c-1; if (compareAndSetState(c, nextc)) return nextc == 0; }}
因为构造方法里面我们设置了资源值,所以在await的时候会调用tryAcquireShared返回-1进行阻塞等待。
而countDown方法则每次调用tryReleaseShared(1)进行资源-1的操作,当资源变为0时,唤醒Sync队列里的节点进行资源获取的操作,从而让阻塞的主线程又活跃起来。
来个例子
场景:游戏需要5个人加入才能开始游戏
public class CountDownLatchLearning { @Test public void test() throws InterruptedException { final CountDownLatch latch = new CountDownLatch(5); for (int i = 0; i < 5; i++) { final int index = i; Thread thread = new Thread(new Runnable() { public void run() { System.out.println("用户:" + index + "加入游戏"); latch.countDown(); } }); thread.start(); } latch.await(); System.out.println("匹配完成,开始游戏。。。"); }}
运行结果
用户:0加入游戏用户:1加入游戏用户:2加入游戏用户:3加入游戏用户:4加入游戏匹配完成,开始游戏。。。