之前有看過AbstractQueueSynchronized(隊列同步器)的使用方式硕淑,這里大家可以看看我的另一篇文章《自定義同步組件構(gòu)建實例及AbstractQueuedSynchronizer使用》。
下面貼出CountDownLatch的源碼(源碼注釋被我減去了):
public class CountDownLatch {
/**
* 這里繼承隊列同步器,并重寫tryAcquireShared(int acquires)缨历、tryReleaseShared(int releases)方法
*/
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L;
Sync(int count) {
setState(count);
}
int getCount() {
return getState();
}
/**
* 只有當CountDownLatch里面的計數(shù)器為0時儒老,才會返回1
* 在AbstractQueuedSynchronizer里面tryAcquireShared(int acquires)表示共享式獲取同步狀態(tài),
* 只有返回值大于等于0的時候表示獲取成功挣棕,反之則表示獲取失敗
*/
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
/**
* 在AbstractQueuedSynchronizer里面tryAcquireShared(int acquires)表示共享式釋放同步狀態(tài)
* 每成功調(diào)用一次這個方法Sync的實例的status值就會減一,當status的值減為0時葱蝗,則不會再減穴张。
*/
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;
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));
}
/**
* countDown:每調(diào)用一次countDown()方法都會使sync成員變量status減一(直到status為0),status為0两曼,則會讓調(diào)用await()方法的地方不在阻塞皂甘,
* 從而達到可以等待多個并發(fā)事件完成的目標
* @author JM
* 2017-2-23 下午10:29:25
* void
*/
public void countDown() {
sync.releaseShared(1);
}
public long getCount() {
return sync.getCount();
}
public String toString() {
return super.toString() + "[Count = " + sync.getCount() + "]";
}
}
看完上面的源碼,其實說來說去CountDownLatch就是一個自定義的同步組件悼凑。
現(xiàn)在來分析一下CountDownLatch實現(xiàn)“等待多個并發(fā)事件完成”的過程:
在new CountDownLatch(int count)的時候就會將CountDownLatch內(nèi)部的Sync初始化偿枕,并將sync的status值初始化為count,每次調(diào)用CountDownLatch對象的countDown()方法都會將sync的status的值減一户辫,當status值減為0時渐夸,線程內(nèi)因為調(diào)用await()而阻塞的地方將會重新執(zhí)行。從而達到“等待多個并發(fā)事件完成”的效果