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

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

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

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

LinkedBlockingQueue也是使用單向鏈表實(shí)現(xiàn)的,其也有兩個(gè)Node,分別用來存放首、尾節(jié)點(diǎn),并且還有一個(gè)初始值為0的原子變量count,用來記錄隊(duì)列元素個(gè)數(shù)。另外還有兩個(gè)ReentrantLock的實(shí)例,分別用來控制元素入隊(duì)和出隊(duì)的原子性,其中takeLock用來控制同時(shí)只有一個(gè)線程可以從隊(duì)列頭獲取元素,其他線程必須等待,putLock控制同時(shí)只能有一個(gè)線程可以獲取鎖,在隊(duì)列尾部添加元素,其他線程必須等待。另外,notEmpty 和 notFull 是條件變量,它們內(nèi)部都有一個(gè)條件隊(duì)列用來存放進(jìn)隊(duì)和出隊(duì)時(shí)被阻塞的線程,其實(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)用線程在LinkedBlockingQueue 實(shí)例上執(zhí)行take、poll 等操作時(shí)需要獲取到 takeLock 鎖,從而保證同時(shí)只有一個(gè)線程可以操作鏈表頭節(jié)點(diǎn)。另外由于條件變量 notEmpty 內(nèi)部的條件隊(duì)列的維護(hù)使用的是takeLock的鎖狀態(tài)管理機(jī)制,所以在調(diào)用notEmpty的await 和signal方法前調(diào)用線程必須先獲取到 takeLock鎖,否則會(huì)拋出IllegalMonitorStateException 異常。notEmpty內(nèi)部則維護(hù)著一個(gè)條件隊(duì)列,當(dāng)線程獲取到takeLock 鎖后調(diào)用 notEmpty的await 方法時(shí),調(diào)用線程會(huì)被阻塞,然后該線程會(huì)被放到notEmpty內(nèi)部的條件隊(duì)列進(jìn)行等待,直到有線程調(diào)用了notEmpty的 signal 方法。

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

如下是LinkedBlockingQueue的無參構(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,用戶也可以自己指定容量,所以從一定程度上可以說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ì)列已滿則丟棄當(dāng)前元素并返回false

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

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

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

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

代碼(7)中的c0說明在執(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í)行,也就是說,一些操作只能在某些條件滿足的情況下才執(zhí)行,在一些條件下執(zhí)行某種操作,在另外一些條件下執(zhí)行另外的操作,需要的朋友可以參考一下
    2022-01-01
  • Java中的CopyOnWriteArrayList容器解析

    Java中的CopyOnWriteArrayList容器解析

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

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

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

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

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

    Java FileInputStream與FileOutputStream使用詳解

    這篇文章主要介紹了Java FileInputStream與FileOutputStream使用詳解,本篇文章通過簡(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切換分支代碼丟失的問題

    解決idea 暫存文件或idea切換分支代碼丟失的問題

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

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

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

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

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

最新評(píng)論

枝江市| 弋阳县| 金华市| 马龙县| 彭泽县| 元阳县| 勃利县| 射洪县| 宜川县| 彩票| 阜宁县| 黄冈市| 崇礼县| 洞头县| 武汉市| 吉林省| 抚松县| 前郭尔| 紫金县| 东兰县| 沈丘县| 汉阴县| 辽阳市| 万荣县| 三台县| 阜南县| 新源县| 房产| 泽州县| 石阡县| 上饶市| 油尖旺区| 同德县| 双桥区| 泰兴市| 新民市| SHOW| 茂名市| 英吉沙县| 通化市| 广饶县|