中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么使用java計數器CountDownLatch

發布時間:2021-11-19 16:16:57 來源:億速云 閱讀:226 作者:iii 欄目:編程語言

本篇內容介紹了“怎么使用java計數器CountDownLatch”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

CountDownLatch簡介

CountDownLatch顧名思義,count + down + latch = 計數 + 減 + 門閂(這么拆分也是便于記憶=_=) 可以理解這個東西就是個計數器,只能減不能加,同時它還有個門閂的作用,當計數器不為0時,門閂是鎖著的;當計數器減到0時,門閂就打開了。

如果你感到懵比的話,可以類比考生考試交卷,考生交一份試卷,計數器就減一。直到考生都交了試卷(計數器為0),監考老師(一個或多個)才能離開考場。至于考生是否做完試卷,監考老師并不關注。只要都交了試卷,他就可以做接下來的工作了。

CountDownLatch實現原理

下面從構造方法開始,一步步解釋實現的原理:構造方法下面是實現的源碼,非常簡短,主要是創建了一個Sync對象。

public CountDownLatch(int count) {if (count < 0) throw new IllegalArgumentException("count < 0");this.sync = new Sync(count);}

Sync對象

private static final class Sync extends AbstractQueuedSynchronizer {private static final long serialVersionUID = 4982264981922014374L;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 zerofor (;;) {int c = getState();if (c == 0)return false;int nextc = c-1;if (compareAndSetState(c, nextc))return nextc == 0;}}}

假設我們是這樣創建的:new CountDownLatch(5)。其實也就相當于new Sync(5),相當于setState(5)。setState其實就是共享鎖資源總數,我們可以暫時理解為設置一個計數器,當前計數器初始值為5。

tryAcquireShared方法其實就是判斷一下當前計數器的值,是否為0了,如果為0的話返回1(返回1的時候,就表示獲取鎖成功,awit()方法就不再阻塞)。

tryReleaseShared方法就是利用CAS的方式,對計數器進行減一的操作,而我們實際上每次調用countDownLatch.countDown()方法的時候,最終都會調到這個方法,對計數器進行減一操作,一直減到0為止。

countDownLatch.await()

public void await() throws InterruptedException { sync.acquireSharedInterruptibly(1); }

代碼很簡單,就一句話(注意acquireSharedInterruptibly()方法是抽象類:AbstractQueuedSynchronizer的一個方法,我們上面提到的Sync繼承了它),我們跟蹤源碼,繼續往下看:

acquireSharedInterruptibly(int arg) public final void acquireSharedInterruptibly(int arg)throws InterruptedException {if (Thread.interrupted())throw new InterruptedException();if (tryAcquireShared(arg) < 0)doAcquireSharedInterruptibly(arg);}

源碼也是非常簡單的,首先判斷了一下,當前線程是否有被中斷,如果沒有的話,就調用tryAcquireShared(int acquires)方法,判斷一下當前線程是否還需要“阻塞”。其實這里調用的tryAcquireShared方法,就是我們上面提到的java.util.concurrent.CountDownLatch.Sync.tryAcquireShared(int)這個方法。

當然,在一開始我們沒有調用過countDownLatch.countDown()方法時,這里tryAcquireShared方法肯定是會返回-1的,因為會進入到doAcquireSharedInterruptibly方法。

doAcquireSharedInterruptibly(int arg)

countDown()方法

// 計數器減1public void countDown() {sync.releaseShared(1); }//調用AQS的releaseShared方法public final boolean releaseShared(int arg) {if (tryReleaseShared(arg)) {//計數器減一doReleaseShared();//喚醒后繼結點,這個時候隊列中可能只有調用過await()的線程節點,也可能隊列為空return true;}return false;}

這個時候,我們應該對于countDownLatch.await()方法是怎么“阻塞”當前線程的,已經非常明白了。其實說白了,就是當你調用了countDownLatch.await()方法后,你當前線程就會進入了一個死循環當中,在這個死循環里面,會不斷的進行判斷,通過調用tryAcquireShared方法,不斷判斷我們上面說的那個計數器,看看它的值是否為0了(為0的時候,其實就是我們調用了足夠多 countDownLatch.countDown()方法的時候),如果是為0的話,tryAcquireShared就會返回1,代碼也會進入到圖中的紅框部分,然后跳出了循環,也就不再“阻塞”當前線程了。

需要注意的是,說是在不停的循環,其實也并非在不停的執行for循環里面的內容,因為在后面調用parkAndCheckInterrupt()方法時,在這個方法里面是會調用 LockSupport.park(this);來掛起當前線程。

CountDownLatch 使用的注意點:

1、只有當count為0時,await之后的程序才夠執行。

2、countDown必須寫在finally中,防止發生異程常時,導致程序死鎖。

使用場景:

比如對于馬拉松比賽,進行排名計算,參賽者的排名,肯定是跑完比賽之后,進行計算得出的,翻譯成Java識別的預發,就是N個線程執行操作,主線程等到N個子線程執行完畢之后,在繼續往下執行。

public static void testCountDownLatch(){int threadCount = 10;final CountDownLatch latch = new CountDownLatch(threadCount);for(int i=0; i< threadCount; i++){new Thread(new Runnable() {@Overridepublic void run() {System.out.println("線程" + Thread.currentThread().getId() + "開始出發");try {Thread.sleep(1000);System.out.println("線程" + Thread.currentThread().getId() + "已到達終點");} catch (InterruptedException e) {e.printStackTrace();} fianlly {latch.countDown();}}}).start();}try {latch.await();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("10個線程已經執行完畢!開始計算排名");}

結果:

線程10開始出發線程13開始出發線程12開始出發線程11開始出發線程14開始出發線程15開始出發線程16開始出發線程17開始出發線程18開始出發線程19開始出發線程14已到達終點線程15已到達終點線程13已到達終點線程12已到達終點線程10已到達終點線程11已到達終點線程16已到達終點線程17已到達終點線程18已到達終點線程19已到達終點10個線程已經執行完畢!開始計算排名

“怎么使用java計數器CountDownLatch”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

荔浦县| 木兰县| 平武县| 甘泉县| 峡江县| 长子县| 都兰县| 旺苍县| 繁昌县| 定边县| 莱阳市| 洛南县| 淮滨县| 临猗县| 钟山县| 博湖县| 灵璧县| 云安县| 威信县| 芦山县| 桂平市| 化州市| 大埔县| 水城县| 嘉黎县| 济宁市| 永州市| 泉州市| 克什克腾旗| 和平区| 晋州市| 武平县| 综艺| 花莲县| 德钦县| 松江区| 安吉县| 根河市| 镇原县| 哈巴河县| 高邑县|