countDownLatch可以实现一个线程或者一些线程需要等待其他线程的任务完成之后才做任务。需要等待执行的线程内调用await()等待其他线程执行完,而被等待的线程内调用countDown()表示当前线程任务执行完成了,当所有的被等待线程都执行完成之后,等待线程继续执行任务。
实现
countDownLatch内部类Sync继承了AQS,对其中关于共享锁的获取进行了实现。将state当作是需要等待的线程数,通过共享锁来实现对多个线程的控制。
使用场景
1、多线程执行完后的汇总操作。汇总线程执行await,多线程任务执行countDown。
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L;
Sync(int count) {// count用于限制被等待线程数
setState(count);
}
int getCount() {
return getState();
}
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;//当state为0时,允许获取锁,表示此时被等待的线程数为0
}
protected boolean tryReleaseShared(int releases) {//当被等待的线程数完成任务之后触发,表示被等待线程执行完成,调用countDown时调用
// Decrement count; signal when transition to zero
for (;;) {
int c = getState();
if (c == 0)
return false;
int nextc = c-1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
}
countDownLatch通过调用Sync的具体方法来实现await和countDown方法的逻辑。
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
public void countDown() {
sync.releaseShared(1);
}
AQS设计用来作为实现同步器的工具,让我们不需要关注其内部是怎么实现线程等待和线程恢复竞争锁。我们只需要实现获取锁的方式是什么。对于state不一定是状态的意思,在这里countDownLatch将state作为被等待线程数使用,在其他地方也可以赋予其他含义。