CountDownLatch
:允许一个或多个线程等待其他线程中执行完成的同步辅助工具。
CountDownLatch使用一个给定的计数初始化。await方法阻塞,直到由于countDown()方法的调用而导致当前计数达到零,之后所有等待线程被释放,并且任何后续的await 调用立即返回。 这是一个一次性的现象 - 计数器无法重置。 如果您需要重置计数器的版本,可以考虑使用CyclicBarrier 。
主要使用await()方法与countDown方法实现,使用示例:
public class CountDownLatchTest {
static CountDownLatch latch;
public static void main(String[] args) {
int n=40;
latch = new CountDownLatch(n);
for (int i=0;i<n;i++) {
new Thread(() -> {
System.out.println("减一");
latch.countDown();
}).start();
}
try {
latch.await();
System.out.println("终于减完了");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**执行结果
减一
... 省略 ...
减一
终于减完了
先看下Sync的源码,如下:
/**
* Synchronization control For CountDownLatch.
* Uses AQS state to represent count.
*/
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L;
//使用AQS的state作为计数器
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;
//使用CAS进行更新,保证线程安全性
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
}
二、CountDownLatch源码
public class CountDownLatch {
private static final class Sync extends AbstractQueuedSynchronizer {
// ... 省略 ...
}
private final Sync sync;
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
public void countDown() {
sync.releaseShared(1);
}
public long getCount() {
return sync.getCount();
}
public String toString() {
return super.toString() + "[Count = " + sync.getCount() + "]";
}
}