CountDownLatch 源码分析
1. 類介紹
一個同步輔助類,在完成一組正在其他線程中執(zhí)行的操作之前,它允許一個或多個線程一直等待。用給定的計數(shù) 初始化 CountDownLatch。由于調(diào)用了 countDown() 方法,所以在當(dāng)前計數(shù)到達零之前,await 方法會一直受阻塞。之后,會釋放所有等待的線程,await 的所有后續(xù)調(diào)用都將立即返回。這種現(xiàn)象只出現(xiàn)一次——計數(shù)無法被重置。
2. 使用場景
在一些應(yīng)用場合中,需要等待某個條件達到要求后才能做后面的事情。
CountDownLatch最重要的方法是countDown()和await()兩個方法,countDown主要是倒數(shù)一次,await是等待倒數(shù)到0,如果沒有到達0,就只有阻塞等待了。
例如:
A 和 B 相約一起吃飯,等A和B都到指定頂點后才能開始吃飯,下面用代碼模擬實現(xiàn)。
示例
public class CountDownLatchTest {static CountDownLatch c = new CountDownLatch(2);public static void main(String[] args) {new Thread(new Runnable() {public void run() {System.out.println("A 我來了");c.countDown();}}).start();new Thread(new Runnable() {public void run() {System.out.println("B 我來了");c.countDown();}}).start();new Thread(new Runnable() {public void run() {try {c.await();System.out.println("開始吃飯...");} catch (InterruptedException e) {e.printStackTrace();}}}).start();} }源碼分析:
需要提前了解:AbstractQueuedSynchronizer 源碼分析
AQS提供了兩種模式:獨占模式&共享模式。CountDownLatch就是一個使用共享模式的自定義同步器實現(xiàn)的共享鎖。
CountDownLatch 代碼不多,主要是通過內(nèi)部類繼承AQS來實現(xiàn)其功能的,下面我們一步一步來分析下源碼:
Sync 內(nèi)部類
private static final class Sync extends AbstractQueuedSynchronizer {private static final long serialVersionUID = 4982264981922014374L;//構(gòu)造Sync對象是初始化AQS中state的數(shù)量(共享鎖的個數(shù))Sync(int count) {setState(count);}//獲取當(dāng)前state的數(shù)量(共享鎖個數(shù))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 zerofor (;;) {int c = getState();if (c == 0)return false;int nextc = c-1;if (compareAndSetState(c, nextc))return nextc == 0;}} }AbstractQueuedSynchronizer 類采用模版模式進行擴展實現(xiàn)其相應(yīng)的功能。子類只需要實現(xiàn)
如下5個方法就能實現(xiàn)其不同功能的鎖。
而CountDownLatch 的內(nèi)部類Sync使用的是共享鎖所以只實現(xiàn)了tryAcquireShared和tryReleaseShared方法。
CountDownLatch的構(gòu)造方法
public CountDownLatch(int count) {if (count < 0) throw new IllegalArgumentException("count < 0");this.sync = new Sync(count); }創(chuàng)建CountDownLatch對象時,需要傳入一個int的計數(shù)器。
await 方法
public void await() throws InterruptedException {sync.acquireSharedInterruptibly(1); }public boolean await(long timeout, TimeUnit unit)throws InterruptedException {return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout)); }await方法調(diào)用AQS的獲得鎖的方法,只有AQS的state狀態(tài)為0時才能獲得鎖,如果state不為0,則需要在AQS的等待隊列中阻塞等待。
public void countDown() {sync.releaseShared(1); }countDown方法則調(diào)用AQS的releaseShared方法,釋放共享鎖,也就是每次將state狀態(tài)每次減一,直到減到0,則喚醒隊列中的所有節(jié)點(線程)。
public long getCount() {return sync.getCount(); }獲取計數(shù)器當(dāng)前值。
本人簡書blog地址:http://www.jianshu.com/u/1f0067e24ff8????
點擊這里快速進入簡書
總結(jié)
以上是生活随笔為你收集整理的CountDownLatch 源码分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AbstractQueuedSynchr
- 下一篇: Semaphore 源码分析