日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

闭锁java_java多线程学习十::::CountDownLatch闭锁

發(fā)布時間:2025/3/20 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 闭锁java_java多线程学习十::::CountDownLatch闭锁 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

請看以下的代碼

package rs.thread.day0504;

import java.util.concurrent.CountDownLatch;

/**

* @auther rs

* @date 2019/5/4 20:32

* @email 529811807@qq.com

* @weixinhao javawjs

*

*/

public class Test10_CountDownLatch {

public static void main(String [] args ){

//執(zhí)行時間

long startTime = System.currentTimeMillis();

//這個是控制幾個線程在執(zhí)行后,在執(zhí)行主線程的任務

int count = 6;

CountDownLatch ld = new CountDownLatch(count);

for(int j =0;j

new Thread(new CountDownLatchThread(ld)){}.start();

}

//等待數(shù)得到0這個數(shù)據(jù)在執(zhí)行

try {

ld.await();

} catch (InterruptedException e) {

e.printStackTrace();

}

long endTime = System.currentTimeMillis();

System.out.println("使用的時間是>>" + (endTime - startTime));

}

}

class CountDownLatchThread implements Runnable{

private CountDownLatch latch ;

public CountDownLatchThread(){}

public CountDownLatchThread(CountDownLatch latch){

this.latch = latch;

}

@Override

public void run() {

for(int i = 0;i<50000;i++){

if(i % 2 == 0){

System.out.println(i);

}

}

//必須控制它減少到0

latch.countDown();

}

}

看了上面的定義和Demo代碼之后,使用就會簡單一點了,一般流程如首先是創(chuàng)建實例 CountDownLatch countDown = new CountDownLatch(2)

需要同步的線程執(zhí)行完之后,計數(shù)-1; countDown.countDown()

需要等待其他線程執(zhí)行完畢之后,再運行的線程,調(diào)用 countDown.await()實現(xiàn)阻塞同步

注意在創(chuàng)建實例是,必須指定初始的計數(shù)值,且應大于0

必須有線程中顯示的調(diào)用了countDown()計數(shù)-1方法;必須有線程顯示調(diào)用了 await()方法(沒有這個就沒有必要使用CountDownLatch了)

由于await()方法會阻塞到計數(shù)為0,如果在代碼邏輯中某個線程漏掉了計數(shù)-1,導致最終計數(shù)一直大于0,直接導致死鎖了

鑒于上面一點,更多的推薦 await(long, TimeUnit)來替代直接使用await()方法,至少不會造成阻塞死只能重啟的情況

應用場景

前面給了一個demo演示如何用,那這個東西在實際的業(yè)務場景中是否會用到呢?

因為確實在一個業(yè)務場景中使用到了,不然也就不會單獨撈出這一節(jié)...

電商的詳情頁,由眾多的數(shù)據(jù)拼裝組成,如可以分成一下幾個模塊交易的收發(fā)貨地址,銷量

商品的基本信息(標題,圖文詳情之類的)

推薦的商品列表

評價的內(nèi)容

....

上面的幾個模塊信息,都是從不同的服務獲取信息,且彼此沒啥關聯(lián);所以為了提高響應,完全可以做成并發(fā)獲取數(shù)據(jù),如線程1獲取交易相關數(shù)據(jù)

線程2獲取商品基本信息

線程3獲取推薦的信息

線程4獲取評價信息

....

但是最終拼裝數(shù)據(jù)并返回給前端,需要等到上面的所有信息都獲取完畢之后,才能返回,這個場景就非常的適合 CountDownLatch來做了在拼裝完整數(shù)據(jù)的線程中調(diào)用 CountDownLatch#await(long, TimeUnit) 等待所有的模塊信息返回

每個模塊信息的獲取,由一個獨立的線程執(zhí)行;執(zhí)行完畢之后調(diào)用 CountDownLatch#countDown() 進行計數(shù)-1

CountDownLatch實現(xiàn)原理就是AQS 的原理

這么好用的功能是怎么實現(xiàn)的呢,下面就來說一說實現(xiàn)它的核心技術原理 AQS。 AQS 全稱 AbstractQueuedSynchronizer,是 java.util.concurrent 中提供的一種高效且可擴展的同步機制。它可以用來實現(xiàn)可以依賴 int 狀態(tài)的同步器,獲取和釋放參數(shù)以及一個內(nèi)部FIFO等待隊列,除了CountDownLatch,ReentrantLock、Semaphore 等功能實現(xiàn)都使用了它。

接下來用 CountDownLatch 來分析一下 AQS 的實現(xiàn)。建議看文章的時候先大致看一下源碼,有助于理解下面所說的內(nèi)容。

在我們的方法中調(diào)用 awit()和countDown()的時候,發(fā)生了幾個關鍵的調(diào)用關系,我畫了一個方法調(diào)用圖。

首先在 CountDownLatch 類內(nèi)部定義了一個 Sync 內(nèi)部類,這個內(nèi)部類就是繼承自 AbstractQueuedSynchronizer 的。并且重寫了方法 tryAcquireShared和tryReleaseShared。例如當調(diào)用 awit()方法時,CountDownLatch 會調(diào)用內(nèi)部類Sync 的 acquireSharedInterruptibly() 方法,然后在這個方法中會調(diào)用 tryAcquireShared 方法,這個方法就是 CountDownLatch 的內(nèi)部類 Sync 里重寫的 AbstractQueuedSynchronizer 的方法。調(diào)用 countDown() 方法同理。

這種方式是使用 AbstractQueuedSynchronizer 的標準化方式,大致分為兩步:

1、內(nèi)部持有繼承自 AbstractQueuedSynchronizer 的對象 Sync;

2、并在 Sync 內(nèi)重寫 AbstractQueuedSynchronizer protected 的部分或全部方法,這些方法包括如下幾個:

總結(jié)

1、AQS 分為獨占模式和共享模式,CountDownLatch 使用了它的共享模式。

2、AQS 當?shù)谝粋€等待線程(被包裝為 Node)要入隊的時候,要保證存在一個 head 節(jié)點,這個 head 節(jié)點不關聯(lián)線程,也就是一個虛節(jié)點。

3、當隊列中的等待節(jié)點(關聯(lián)線程的,非 head 節(jié)點)搶到鎖,將這個節(jié)點設置為 head 節(jié)點。

4、第一次自旋搶鎖失敗后,waitStatus 會被設置為 -1(SIGNAL),第二次再失敗,就會被 LockSupport 阻塞掛起。

5、如果一個節(jié)點的前置節(jié)點為 SIGNAL 狀態(tài),則這個節(jié)點可以嘗試搶占鎖。

歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明出處!

github: rs1314

歡迎關注共公眾號微信 : java微技術

分享我的學習之路和各種java技術,教程資料

總結(jié)

以上是生活随笔為你收集整理的闭锁java_java多线程学习十::::CountDownLatch闭锁的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。