前言
- 一种同步帮助,它允许一个或多个线程等待,直到在其他线程中执行的一组操作完成为止。
- {@code CountDownLatch}用给定的计数初始化。
- {@link #await await}方法将阻塞,直到由于调用{@link #countDown}方法而导致当前计数达到零为止,此后所有等待线程都将被释放,{@link #await await}的所有后续调用将立即返回。
- 这是一种一次性现象-无法重置计数。
- 如果需要用于重置计数的版本,请考虑使用{@link CyclicBarrier}。
- {@code CountDownLatch}是一种多功能的同步工具,可以用于多种用途。
- 初始化为{@code CountDownLatch}的计数为一个简单的on /off锁存器或门:调用{@link #await await}的所有线程都在门处等待,直到被调用{@link#倒数}。
- 初始化为N的{@code CountDownLatch}可用于使一个线程等待,直到N个线程完成某项操作或某项操作已完成N次。
- {@code CountDownLatch}的一个有用属性是,它不需要调用{@code countDown}的线程在继续计数之前就等待计数达到零,它只是防止任何线程经过{@link #await await },直到所有线程都可以通过。
- 用法示例:这是一对类,其中一组工作线程使用两个倒计时锁存器:第一个是启动信号,它防止任何工作程序继续进行,直到驱动程序为它们准备好为止。
- 第二个是完成信号,驾驶员可以等待所有工人完成操作。
- 另一个典型用法是将问题分为N个部分,用Runnable描述每个部分,该Runnable执行该部分并在锁存器上递减计数,然后将所有Runnable排队给执行程序。
- 当所有子部分都完成时,协调线程将能够通过等待。
- (当线程必须以此方式反复递减计数时,请使用{@link CyclicBarrier}。)
源码
package java.util.concurrent;
public class CountDownLatch {
/**
* Synchronization control For CountDownLatch.
* Uses AQS state to represent count.
*/
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L;
Sync(int count) {
setState(count);
}
int getCount() {
return getState();
}
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
protected boolean tryReleaseShared(int releases) {
// 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;
}
}
}
private final Sync sync;
/**
* 构造一个{@code CountDownLatch},并使用给定的计数初始化。
*/
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
/**
* 使当前线程等待,直到锁存器计数到零为止,除非该线程{@linkplain Thread#interrupt interrupted}。
* 如果当前计数为零,则此方法立即返回。
* 如果当前计数大于零,则出于线程调度目的,当前线程将被禁用,并处于休眠状态,直到发生以下两种情况之一为止:
* 由于调用{@link
* 如果当前线程:在进入此方法时设置了其中断状态;
* 或在等待期间{@linkplain Thread#interrupt被中断},则抛出{@link InterruptedException}并清除当前线程的中断状态。
*/
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
/**
* 使当前线程等待,直到锁存器计数到零为止,除非该线程{@linkplain Thread#interrupt interrupted},或者经过了指定的等待时间。
* 如果当前计数为零,则此方法将立即返回值{@code true}。
* 如果当前计数大于零,则出于线程调度目的,当前线程将被禁用,并处于休眠状态,直到发生以下三种情况之一为止:由于调用{@link
* 如果计数达到零,则该方法返回值{@code true}。
* 如果当前线程:在进入此方法时设置了其中断状态;或在等待期间{@linkplain Thread#interrupt被中断},则抛出{@link InterruptedException}并清除当前线程的中断状态。
* 如果经过了指定的等待时间,则返回值{@code false}。
* 如果时间小于或等于零,则该方法将根本不等待。
*/
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
/**
* <p>If the current count equals zero then nothing happens.
* 减少锁存器的计数,如果计数达到零,则释放所有等待线程。
* 如果当前计数大于零,则将其递减。
* 如果新计数为零,则将重新启用所有等待线程以进行线程调度。
* 如果当前计数等于零,那么什么也不会发生。
*/
public void countDown() {
sync.releaseShared(1);
}
/**
* 返回当前计数。此方法通常用于调试和测试目的。
*/
public long getCount() {
return sync.getCount();
}
/**
* 返回标识此锁存器及其状态的字符串。括号中的状态包括字符串{@code“ Count =”},后跟当前计数。
*/
public String toString() {
return super.toString() + "[Count = " + sync.getCount() + "]";
}
}