CountDownLatch
(锁存器/闭锁)是基于同步器实现的同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
用计数值 N 初始化的 CountDownLatch 可以使一个或多个线程在其他 N 个线程完成某项操作之前一直等待,或者使其在某项操作完成 N 次之前一直等待。
创建实例
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L;
Sync(int count) {
// 写入状态值
setState(count);
}
int getCount() {
return getState();
}
/**
* 只有当同步状态为 0 时才能获取成功,否则进入阻塞
* created by ZXD at 15 Dec 2018 T 12:05:56
* @param acquires
* @return
*/
@Override
protected int tryAcquireShared(int acquires) {
return getState() == 0 ? 1 : -1;
}
/**
* 尝试将状态值递减 1,如果递减到 0,则释放在闭锁上阻塞等待的所有线程
*/
@Override
protected boolean tryReleaseShared(int releases) {
// Decrement count; signal when transition to zero
for (;;) {
final int c = getState();
if (c == 0) {
return false;
}
// 状态值递减 1
final int nextc = c - 1;
if (compareAndSetState(c, nextc)) {
// 已经递减到 0,则返回 true
return nextc == 0;
}
}
}
}
private final Sync sync;
/**
* 创建计数值为 count 的闭锁
*/
public CountDownLatch(int count) {
if (count < 0) {
throw new IllegalArgumentException("count < 0");
}
sync = new Sync(count);
}
同步阻塞
/**
* 阻塞等待闭锁的状态值递减到 0、或线程被中断为止
*/
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
/**
* 在指定的超时时间内阻塞等待闭锁的状态值递减到 0、或线程被中断为止
*/
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
递减闭锁状态值,如果递减到 0,则释放所有在闭锁上阻塞等待的线程
/**
* 递减闭锁状态值,如果递减到 0,则释放所有在闭锁上阻塞等待的线程
*/
public void countDown() {
sync.releaseShared(1);
}