BlockQueue 是什麼?

本文內容如有錯誤、不足之處,歡迎技術愛好者們一同探討,在本文下面討論區留言,感謝。

簡述

阻塞隊列:當線程隊列是空時,從隊列中獲取元素的操作將會被阻塞;當線程隊列是滿時,往隊列裏添加元素的操作將會被阻塞。

Java 5 開始出現存在 java.util.concurrent 包下,阻塞隊列是一個隊列,當嘗試從隊列中出隊並且隊列爲空時,或者嘗試將項目入隊並且隊列已滿時,它將阻塞。嘗試從空隊列中出隊的線程被阻止,直到其他線程將一個項目插入隊列中爲止。嘗試使一個項目進入完整隊列的線程被阻塞,直到某個其他線程在隊列中騰出空間爲止,方法是使一個或多個項目出隊或完全清除隊列。

原理

原理示意圖片:
圖片地址:http://tutorials.jenkov.com/java-concurrency/blocking-queues.html

在這裏插入圖片描述
下面是一個簡單的BlockQueue的實現:

public class BlockingQueue {
  private List queue = new LinkedList();
  private int  limit = 10;
  public BlockingQueue(int limit){
    this.limit = limit;
  }
  
  public synchronized void enqueue(Object item)throws InterruptedException  {
    while(this.queue.size() == this.limit) {
      wait();
    }
    if(this.queue.size() == 0) {
      notifyAll();
    }
    this.queue.add(item);
  }
  
  public synchronized Object dequeue() throws InterruptedException{
    while(this.queue.size() == 0){
      wait();
    }
    if(this.queue.size() == this.limit){
      notifyAll();
    }
    return this.queue.remove(0);
  }
}

操作代碼:

// 調用 BlockingQueue 方法的Java程序演示
  
import java.util.concurrent.*; 
import java.util.*; 
  
public class GFG { 
    public static void main(String[] args) 
        throws InterruptedException 
    { 
  
        // ArrayBlockingQueue 的邊界大小
        int capacity = 5; 
  
        // 創建 ArrayBlockingQueue 
        ArrayBlockingQueue<String>  queue = new ArrayBlockingQueue<String>(capacity); 
  
        // 使用put()方法添加元素 
        queue.put("StarWars"); 
        queue.put("SuperMan"); 
        queue.put("Flash"); 
        queue.put("BatMan"); 
        queue.put("Avengers"); 
  
        // 打印隊列
        System.out.println("queue contains "+ queue); 
  
        // 移除一些元素
        queue.remove(); 
        queue.remove(); 
		queue.put("CaptainAmerica"); 
        queue.put("Thor"); 
  
        System.out.println("queue contains " + queue); 
    } 
} 

輸出結果:

queue contains [StarWars, SuperMan, Flash, BatMan, Avengers]
queue contains [Flash, BatMan, Avengers, CaptainAmerica, Thor]

操作

BlockingQueue方法有四種形式,它們以不同的方式處理操作,這些操作可能無法滿足開發需求,但將來可能會滿足:第一種拋出異常,第二種返回特殊值( null或false,具體取決於操作),第三個塊將無限期地阻塞當前線程,直到操作成功爲止;第四個塊僅在給定的最大時間限制內超時。

下表總結了這些方法:

方法類型 拋出異常 特殊值 阻塞 超時
插入 add(e) offer(e) put(e) offer(e,time,unit)
移除 remove() poll() take() poll(time,unit)
檢查 element() peek()

這4種不同的行爲集意味着:

  • 引發異常:如果無法立即進行嘗試的操作,則會引發異常。
  • 特殊值:如果無法立即嘗試操作,則會返回一個特殊值(通常爲true / false)。
  • 阻塞:如果無法立即進行嘗試的操作,則該方法調用將一直阻塞直到可行爲止。
  • 超時:如果無法立即進行嘗試的操作,則該方法調用將一直阻塞直到成功,但等待時間不得長於給定的超時。返回一個特殊值,告訴操作是否成功(通常爲true / false)。

下面是一個生產者消費者的案例使用BlockQueue:

class Producer implements Runnable {
   private final BlockingQueue queue;
   Producer(BlockingQueue q) { queue = q; }
   public void run() {
     try {
       while (true) { queue.put(produce()); }
     } catch (InterruptedException ex) { ... handle ...}
   }
   Object produce() { ... }
 }

 class Consumer implements Runnable {
   private final BlockingQueue queue;
   Consumer(BlockingQueue q) { queue = q; }
   public void run() {
     try {
       while (true) { consume(queue.take()); }
     } catch (InterruptedException ex) { ... handle ...}
   }
   void consume(Object x) { ... }
 }

 class Setup {
   void main() {
     BlockingQueue q = new SomeQueueImplementation();
     Producer p = new Producer(q);
     Consumer c1 = new Consumer(q);
     Consumer c2 = new Consumer(q);
     new Thread(p).start();
     new Thread(c1).start();
     new Thread(c2).start();
   }
 }

參考資料

Blocking Queues

Interface BlockingQueue

Java BlockingQueue

BlockingQueue Interface in Java

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章