- CountDownLatch 定義
CountDownLatch 可以理解為一個簡單的計數(shù)器, 首先設(shè)定計數(shù)的值, 然后進行調(diào)用 await(PS: 調(diào)用 await 后, CountDownLatch會判斷 AQS中State值是否為0, 不為0, 則線程節(jié)點進入 AQS的 Sync Queue 里面, 處于阻塞狀態(tài)), 這時線程會阻塞, 直到AQS.state變成0, 則進行喚醒所有調(diào)用的 awiat 的線程
特點: 簡單易用, 最常用于 Future 的實現(xiàn)
看下面的代碼:
import java.util.concurrent.*;
/**
* Created by wzx on 1/12/18.
*/
public class KFuture<V> implements Future<V> {
private CountDownLatch latch; // 控制獲取值等待
private volatile V result; // 執(zhí)行結(jié)果
public KFuture() {
latch = new CountDownLatch(1);
}
/**
* cancel 執(zhí)行計劃
*/
public boolean cancel(boolean ignored) {
boolean cancelled = false;
if (latch.getCount() == 1) {
latch.countDown();
cancelled = true;
}
return cancelled;
}
/**
* 判斷是否 cancel
*/
public boolean isCancelled() {
return latch.getCount() == 0 && result == null;
}
/**
* 判斷任務(wù)是否執(zhí)行
*/
@Override
public boolean isDone() {
return result != null;
}
/**
* 獲取 result
*/
public V get() throws InterruptedException {
try {
latch.await();
return result;
} catch (InterruptedException e) {
throw new Error(e);
}
}
/**
* 定時獲取 result
*/
@Override
public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
try {
latch.await(timeout, unit);
return result;
} catch (InterruptedException e) {
throw new Error(e);
}
}
}
- CountDownLatch 構(gòu)造函數(shù)
CountDownLatch 的內(nèi)部功能都是由 Sync 來實現(xiàn)的
/**
* 指定 latch 的數(shù)量
*/
public CountDownLatch(int count){
if(count < 0) throw new IllegalArgumentException(" count < 0 ");
this.sync = new Sync(count);
}
3. CountDownLatch 內(nèi)部類 Sync
Sync 繼承 AQS, 代理實現(xiàn) await, coutDown
/**
* Synchronization control For CountDownLatch
* Use AQS state to represent count
*/
/**
* AQS 的繼承類, 主要的 獲取 釋放操作
*/
private static final class Sync extends AbstractQueuedSynchronizer{
private static final long serialVersionUID = 4982264981922014374L;
Sync(int count){
setState(count);
}
int getCount(){
return getState();
}
/**
* 判斷是否正真的進行到了latch的位置, 也就是getState() == 0
*/
protected int tryAcquireShared(int acquires){
return (getState() == 0)? 1 : -1;
}
/**
* 進行釋放
*/
protected boolean tryReleaseShared(int release){
// 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 等待方法 awaitXX
/**
* 判斷是否到 latch, 也就是 getState() == 0
*/
public void await() throws InterruptedException{
sync.acquireSharedInterruptibly(1);
}
/**
* 進行指定超時的 await
*/
public boolean await(long timeout, TimeUnit unit) throws InterruptedException{
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
- CountDownLatch 獲取資源方法 countDown
/**
* 釋放獲取 latch 的數(shù)量
*/
public void countDown(){
sync.releaseShared(1);
}
- 總結(jié)
CountDownLatch主要用于控制資源的獲取, 設(shè)定閥值, 一直 coutDown, 直到計數(shù)器為 0為止; CountDownLatch 主要用 AQS的共享方式; 在方法上最大的區(qū)別是調(diào)用 countDown()方法其實是獲取 AQS內(nèi)部的共享資源, 直到獲取到 0 為止; 但要正真理解 CountDownLatch, 還需要看AQS的源碼