CountDownLatch源碼分析

  1. 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);
        }
    }
}
  1. 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;
            }
        }
    }
}
  1. 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));
}
  1. CountDownLatch 獲取資源方法 countDown
/**
 * 釋放獲取 latch 的數(shù)量
 */
public void countDown(){
    sync.releaseShared(1);
}
  1. 總結(jié)
    CountDownLatch主要用于控制資源的獲取, 設(shè)定閥值, 一直 coutDown, 直到計數(shù)器為 0為止; CountDownLatch 主要用 AQS的共享方式; 在方法上最大的區(qū)別是調(diào)用 countDown()方法其實是獲取 AQS內(nèi)部的共享資源, 直到獲取到 0 為止; 但要正真理解 CountDownLatch, 還需要看AQS的源碼
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容