閱讀763 返回首頁    go 阿裏雲 go 技術社區[雲棲]


阻塞隊列

阻塞隊列與普通隊列的區別在於,當隊列是空的時,從隊列中獲取元素的操作將會被阻塞,或者當隊列是滿時,往隊列裏添加元素的操作會被阻塞。試圖從空 的阻塞隊列中獲取元素的線程將會被阻塞,直到其他的線程往空的隊列插入新的元素。同樣,試圖往已滿的阻塞隊列中添加新元素的線程同樣也會被阻塞,直到其他 的線程使隊列重新變得空閑起來,如從隊列中移除一個或者多個元素,或者完全清空隊列,下圖展示了如何通過阻塞隊列來合作:



線程1往阻塞隊列中添加元素,而線程2從阻塞隊列中移除元素

從5.0開始,JDK在java.util.concurrent包裏提供了阻塞隊列的官方實現。盡管JDK中已經包含了阻塞隊列的官方實現,但是熟悉其背後的原理還是很有幫助的。

阻塞隊列的實現

阻塞隊列的實現類似於帶上限的Semaphore的實現。下麵是阻塞隊列的一個簡單實現

01 public class BlockingQueue {
02  
03 private List queue = new LinkedList();
04  
05 private int  limit = 10;
06  
07 public BlockingQueue(int limit){
08  
09 this.limit = limit;
10  
11 }
12  
13 public synchronized void enqueue(Object item)
14  
15 throws InterruptedException  {
16  
17 while(this.queue.size() == this.limit) {
18  
19 wait();
20  
21 }
22  
23 if(this.queue.size() == 0) {
24  
25 notifyAll();
26  
27 }
28  
29 this.queue.add(item);
30  
31 }
32  
33 public synchronized Object dequeue()
34  
35 throws InterruptedException{
36  
37 while(this.queue.size() == 0){
38  
39 wait();
40  
41 }
42  
43 if(this.queue.size() == this.limit){
44  
45 notifyAll();
46  
47 }
48  
49 return this.queue.remove(0);
50  
51 }
52  
53 }

必須注意到,在enqueue和dequeue方法內部,隻有隊列的大小等於上限(limit)或者下限(0)時,才調用notifyAll方法。 如果隊列的大小既不等於上限,也不等於下限,任何線程調用enqueue或者dequeue方法時,都不會阻塞,都能夠正常的往隊列中添加或者移除元素。


文章轉自 並發編程網-ifeve.com

最後更新:2017-05-22 18:01:46

  上一篇:go  阿裏雲總裁胡曉明40個精彩回答 涉及CDN、價格戰、生態競爭等
  下一篇:go  從Java視角理解係統結構(二)CPU緩存