最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入理解Java并發(fā)編程之LinkedBlockingQueue隊(duì)列

 更新時(shí)間:2022年04月15日 15:20:46   作者:派大大大星  
本文主要介紹了Java并發(fā)編程之LinkedBlockingQueue隊(duì)列,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前面一篇文章我們介紹了使用CAS算法實(shí)現(xiàn)的非阻塞隊(duì)列ConcurrentLinedQueue, 下面我們來(lái)介紹使用獨(dú)占鎖實(shí)現(xiàn)的阻塞隊(duì)列LinkedBlockingQueue。

LinkedBlockingQueue也是使用單向鏈表實(shí)現(xiàn)的,其也有兩個(gè)Node,分別用來(lái)存放首、尾節(jié)點(diǎn),并且還有一個(gè)初始值為0的原子變量count,用來(lái)記錄隊(duì)列元素個(gè)數(shù)。另外還有兩個(gè)ReentrantLock的實(shí)例,分別用來(lái)控制元素入隊(duì)和出隊(duì)的原子性,其中takeLock用來(lái)控制同時(shí)只有一個(gè)線(xiàn)程可以從隊(duì)列頭獲取元素,其他線(xiàn)程必須等待,putLock控制同時(shí)只能有一個(gè)線(xiàn)程可以獲取鎖,在隊(duì)列尾部添加元素,其他線(xiàn)程必須等待。另外,notEmpty 和 notFull 是條件變量,它們內(nèi)部都有一個(gè)條件隊(duì)列用來(lái)存放進(jìn)隊(duì)和出隊(duì)時(shí)被阻塞的線(xiàn)程,其實(shí)這是生產(chǎn)者-消費(fèi)者模型。如下是獨(dú)占鎖的創(chuàng)建代碼。

private final AtomicInteger count = new AtomicInteger();

/** Lock held by take, poll, etc */
private final ReentrantLock takeLock = new ReentrantLock();

/** Wait queue for waiting takes */
private final Condition notEmpty = takeLock.newCondition();

/** Lock held by put, offer, etc */
private final ReentrantLock putLock = new ReentrantLock();

/** Wait queue for waiting puts */
private final Condition notFull = putLock.newCondition();
  • 當(dāng)調(diào)用線(xiàn)程在LinkedBlockingQueue 實(shí)例上執(zhí)行take、poll 等操作時(shí)需要獲取到 takeLock 鎖,從而保證同時(shí)只有一個(gè)線(xiàn)程可以操作鏈表頭節(jié)點(diǎn)。另外由于條件變量 notEmpty 內(nèi)部的條件隊(duì)列的維護(hù)使用的是takeLock的鎖狀態(tài)管理機(jī)制,所以在調(diào)用notEmpty的await 和signal方法前調(diào)用線(xiàn)程必須先獲取到 takeLock鎖,否則會(huì)拋出IllegalMonitorStateException 異常。notEmpty內(nèi)部則維護(hù)著一個(gè)條件隊(duì)列,當(dāng)線(xiàn)程獲取到takeLock 鎖后調(diào)用 notEmpty的await 方法時(shí),調(diào)用線(xiàn)程會(huì)被阻塞,然后該線(xiàn)程會(huì)被放到notEmpty內(nèi)部的條件隊(duì)列進(jìn)行等待,直到有線(xiàn)程調(diào)用了notEmpty的 signal 方法。

  • 在LinkedBlockingQueue實(shí)例上執(zhí)行put、offer等操作時(shí)需要獲取到putLock鎖,從而保證同時(shí)只有一個(gè)線(xiàn)程可以操作鏈表尾節(jié)點(diǎn)。同樣由于條件變量 notFull 內(nèi)部的條件隊(duì)列的維護(hù)使用的是putLock的鎖狀態(tài)管理機(jī)制,所以在調(diào)用 notFull 的 await 和 signal 方法前調(diào)用線(xiàn)程必須先獲取到putLock鎖,否則會(huì)拋出 IllegalMonitorStateException 異常。notFull 內(nèi)部則維護(hù)著一個(gè)條件隊(duì)列,當(dāng)線(xiàn)程獲取到 putLock 鎖后調(diào)用notFull的await 方法時(shí),調(diào)用線(xiàn)程會(huì)被阻塞,然后該線(xiàn)程會(huì)被放到notFull 內(nèi)部的條件隊(duì)列進(jìn)行等待,直到有線(xiàn)程調(diào)用了 notFull 的 signal 方法。如下是LinkedBlockingQueue 的無(wú)參構(gòu)造函數(shù)的代碼。

如下是LinkedBlockingQueue的無(wú)參構(gòu)造代碼

public static final int MAX_VALUE = 0x7fffffff;
public LinkedBlockingQueue() {
    this(Integer.MAX_VALUE);
}


public LinkedBlockingQueue(int capacity) {
    if (capacity <= 0) throw new IllegalAgrumentException();
    this.capacity = capacity;
    last = head = new Node<E>(null);
}

由該代碼可知,默認(rèn)隊(duì)列容量為0x7fffffff,用戶(hù)也可以自己指定容量,所以從一定程度上可以說(shuō)LinkedBlockingQueue是有界阻塞隊(duì)列。

offer操作

public boolean offer(E e) {
//(1)
    if (e == null) throw new NullPointerException();
    //(2)
    final AtomicInteger count = this.count;
    if (count.get() == capacity)
        return false;
        //(3)
    int c = -1;
    Node<E> node = new Node<E>(e);
    final ReentrantLock putLock = this.putLock;
    putLock.lock();
    try {
    //(4)
        if (count.get() < capacity) {
            enqueue(node);
            c = count.getAndIncrement();
            //(5)
            if (c + 1 < capacity)
                notFull.signal();
        }
    } finally {
    //(6)
        putLock.unlock();
    }
    //(7)
    if (c == 0)
        signalNotEmpty();
        //(8)
    return c >= 0;
}

代碼(2)判斷如果當(dāng)前隊(duì)列已滿(mǎn)則丟棄當(dāng)前元素并返回false

代碼(3)獲取到 putLock 鎖,當(dāng)前線(xiàn)程獲取到該鎖后,則其他調(diào)用put和 offer操的線(xiàn)程將會(huì)被阻塞(阻塞的線(xiàn)程被放到putLock鎖的AQS阻塞隊(duì)列)。

代碼(4)這里重新判斷當(dāng)前隊(duì)列是否滿(mǎn),這是因?yàn)樵趫?zhí)行代碼(2)和獲取到 putLock 鎖期間可能其他線(xiàn)程通過(guò) put 或者offer 操作向隊(duì)列里面添加了新元素。重新判斯隊(duì)列確實(shí)不滿(mǎn)則新元素入隊(duì),并遞增計(jì)數(shù)器。

代碼(5)判斷如果新元素入隊(duì)后隊(duì)列還有空閑空間,則喚醒notFull的條件隊(duì)列里面因?yàn)檎{(diào)用了notFull的await操作(比如執(zhí)行put方法而隊(duì)列滿(mǎn)了的時(shí)候)而被阻塞的一個(gè)線(xiàn)程,因?yàn)殛?duì)列現(xiàn)在有空閑所以這里可以提前喚醒一個(gè)入隊(duì)線(xiàn)程。

代碼(6)則釋放獲取的putLock 鎖,這里要注意,鎖的釋放一定要在finally里面做因?yàn)榧词箃ry塊拋出異常了,finally也是會(huì)被執(zhí)行到。另外釋放鎖后其他因?yàn)檎{(diào)用put 操作而被阻塞的線(xiàn)程將會(huì)有一個(gè)獲取到該鎖。

代碼(7)中的c0說(shuō)明在執(zhí)行代碼(6)釋放鎖時(shí)隊(duì)列里面至少有一個(gè)元素,隊(duì)列里面有元素則執(zhí)行signalNotEmpty操作.

到此這篇關(guān)于深入理解Java并發(fā)編程之LinkedBlockingQueue隊(duì)列的文章就介紹到這了,更多相關(guān)Java LinkedBlockingQueue隊(duì)列內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • @JsonDeserialize和@JsonSerialize注解的使用方式

    @JsonDeserialize和@JsonSerialize注解的使用方式

    這篇文章主要介紹了@JsonDeserialize和@JsonSerialize注解的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • Java程序控制邏輯—流程控制

    Java程序控制邏輯—流程控制

    這篇文章主要介紹了Java程序的控制邏輯流程控制,流程控制中最基本的就是條件執(zhí)行,也就是說(shuō),一些操作只能在某些條件滿(mǎn)足的情況下才執(zhí)行,在一些條件下執(zhí)行某種操作,在另外一些條件下執(zhí)行另外的操作,需要的朋友可以參考一下
    2022-01-01
  • Java中的CopyOnWriteArrayList容器解析

    Java中的CopyOnWriteArrayList容器解析

    這篇文章主要介紹了Java中的CopyOnWriteArrayList容器解析,CopyOnWriteArrayList容器允許并發(fā)讀,讀操作是無(wú)鎖的,性能較高。至于寫(xiě)操作,比如向容器中添加一個(gè)元素,則首先將當(dāng)前容器復(fù)制一份,然后在新副本上執(zhí)行寫(xiě)操作,需要的朋友可以參考下
    2023-12-12
  • Java編程之多線(xiàn)程死鎖與線(xiàn)程間通信簡(jiǎn)單實(shí)現(xiàn)代碼

    Java編程之多線(xiàn)程死鎖與線(xiàn)程間通信簡(jiǎn)單實(shí)現(xiàn)代碼

    這篇文章主要介紹了Java編程之多線(xiàn)程死鎖與線(xiàn)程間通信簡(jiǎn)單實(shí)現(xiàn)代碼,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-10-10
  • JAVA對(duì)象JSON數(shù)據(jù)互相轉(zhuǎn)換的四種常見(jiàn)情況

    JAVA對(duì)象JSON數(shù)據(jù)互相轉(zhuǎn)換的四種常見(jiàn)情況

    這篇文章主要介紹了JAVA對(duì)象JSON數(shù)據(jù)互相轉(zhuǎn)換的四種常見(jiàn)情況,需要的朋友可以參考下
    2014-04-04
  • Java FileInputStream與FileOutputStream使用詳解

    Java FileInputStream與FileOutputStream使用詳解

    這篇文章主要介紹了Java FileInputStream與FileOutputStream使用詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • Struts中使用validate()輸入校驗(yàn)方法詳解

    Struts中使用validate()輸入校驗(yàn)方法詳解

    這篇文章主要介紹了Struts中使用validate()輸入校驗(yàn)方法,本文介紹的非常詳細(xì),具有參考借鑒價(jià)值,感興趣的朋友一起看看吧
    2016-09-09
  • 解決idea 暫存文件或idea切換分支代碼丟失的問(wèn)題

    解決idea 暫存文件或idea切換分支代碼丟失的問(wèn)題

    這篇文章主要介紹了解決idea 暫存文件或idea切換分支代碼丟失的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-02-02
  • java 與web服務(wù)器鏈接的實(shí)例

    java 與web服務(wù)器鏈接的實(shí)例

    這篇文章主要介紹了java 與web服務(wù)器鏈接的實(shí)例的相關(guān)資料,使用net.Socket類(lèi)sock.getInetAddress()方法獲得與Web服務(wù)器連接,需要的朋友可以參考下
    2017-07-07
  • Java分批將List數(shù)據(jù)導(dǎo)入數(shù)據(jù)庫(kù)的解決過(guò)程

    Java分批將List數(shù)據(jù)導(dǎo)入數(shù)據(jù)庫(kù)的解決過(guò)程

    這篇文章主要給大家介紹了關(guān)于Java分批將List數(shù)據(jù)導(dǎo)入數(shù)據(jù)庫(kù)的解決過(guò)程,文中通過(guò)代碼示例介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2023-08-08

最新評(píng)論

凉山| 从化市| 孝昌县| 屯门区| 濮阳县| 韩城市| 嵊泗县| 长顺县| 吉木乃县| 闸北区| 佳木斯市| 嘉祥县| 垫江县| 防城港市| 嘉峪关市| 青铜峡市| 平罗县| 黔西县| 桐梓县| 内江市| 武陟县| 金坛市| 游戏| 师宗县| 信阳市| 健康| 普兰县| 临高县| 克什克腾旗| 益阳市| 平阴县| 花莲市| 贵德县| 万安县| 辽阳县| 丹寨县| 新民市| 璧山县| 永丰县| 青川县| 松桃|