Java並發包分析 BlockingQueue

2021-07-31 20:11:57 字數 2552 閱讀 2835

arrayblockingqueue顧名思義是一種陣列形式的阻塞佇列,其自然就有陣列的特點,即佇列的長度不可改變,只有初始化的時候指定。

下面,我們看一下例子。

public

class

arrayblock

public blockingqueuegetblockingqueue()

}

建立乙個大小為3的arrayblockingqueue,下面是乙個生產者和消費者,通過arrayblockingqueue實現生產者/消費者模型。

public class

producer

extends

thread

catch (interruptedexception e) }}

public producer(arrayblock arrayblock)

}public class

costumer

extends

thread

@override

public void run() catch (interruptedexception e) }}

}

測試過程就不放了,直接放出結果:

producer 生產資料

producer 生產資料

producer 生產資料

costumer 取出資料 0

producer 生產資料

costumer 取出資料 1

producer 生產資料

costumer 取出資料 2

costumer 取出資料 3

costumer 取出資料 4

這可以看出put方法與take方法均是阻塞的方法。當佇列已經滿的時候,就會阻塞放入方法,當隊列為空的時候,就會阻塞取出方法。

下面,我們主要看這個兩個方法,究竟是如何實現阻塞的。

** put方法 **

public

void

put(e e) throws interruptedexception finally

}

put方法是將元素放入到佇列中,這裡面可以看出是用過lock類與condition類來實現的,即通過等待/通知機制實現的阻塞佇列。這裡notfull是乙個條件,當佇列已經滿的時候,就會執行await方法,如果沒有滿就執行入隊(enqueue)方法。這裡,判斷佇列已滿用的是count == items.length。接下來,我們看一下take方法,來看看取資料的阻塞。

** take方法**

public e take() throws interruptedexception  finally 

}

這裡,與put方法類似,當元素為0時,就會執行await方法,上面方法中都沒有直接說明signal方法的執行。其實該方法是入隊與出隊的方法中實現的。也就是當執行notfull.await()時,是通過dequeue()方法來通知停止等待的,可以放入元素。當執行到notempty.await()時,是通過enqueue來通知結束阻塞,可以取出元素。

linkedblockingqueue顧名思義是乙個鍊錶形式的阻塞佇列,不同於arrayblockingqueue。如果不指定容量,則預設是integer.max_value。也就是說他是乙個無界阻塞佇列。他的例子與上面的類似,但是其put與take方法實現不同於arrayblockingqueue,但兩者大致思路一致。我們只看一下put實現:

** put方法**

public void put(e e) throws

interruptedexception

enqueue(node);

c = count.getandincrement();

if (c + 1

< capacity)

notfull.signal();

} finally

if (c == 0)

signalnotempty();

}

這裡阻塞的本質實現也是通過condition類的等待/通知機制。但是有幾點不同:

第一 這裡用了乙個原子類的count計數,官方的給的注釋是即使沒有鎖來提供保護,也能保證執行緒安全,實現wait guard。

第二 arrayblockingqueue的通知是在入隊與出隊的方法中,linkedblockingqueue則不是,並且插入之後不滿的時候,還有通知其他await的執行緒。

第三 arrayblockingqueue的lock一直是乙個,也就是put/take是用的乙個鎖,放與取無法實現並行。但是linkedblockingqueue是兩個鎖,放乙個鎖,取乙個鎖,可以實現put/take的並行,要高效一些。

synchronousqueue顧名思義是同步佇列,特點不同於上面的阻塞佇列,他是乙個無界非快取的佇列,準確說他不儲存元素,放入的元素,只有等待取走元素之後才能放入。也就是說任意時刻:

Java並發包分析 BlockingQueue

arrayblockingqueue顧名思義是一種陣列形式的阻塞佇列,其自然就有陣列的特點,即佇列的長度不可改變,只有初始化的時候指定。下面,我們看一下例子。public class arrayblock public blockingqueuegetblockingqueue 建立乙個大小為3的a...

java並發包之ConcurrentHashMap

1.hashentry類static final class hashentry 2.segment類static final class segmentextends reentrantlock implements serializable 設定 table 引用到這個新生成的 hashentr...

實戰Java高併發程式設計(三)JDK並發包

同步控制 重入鎖 重入鎖可以完全替代synchronized關鍵字。其使用方法如下 public reentrantlock lock new reentrantlock public void run finally 由於其通過人工進行lock和unlock,因此比synchronized更好控制...