JUC之阻塞隊列(BlockingQueue)基礎

阻塞隊列

阻塞隊列(BlockingQueue)是一個支持兩個附加操作的隊列。這兩個附加的操作支持阻塞的插入和移除方法。

阻塞隊列常用於生產者和消費者的場景:

當隊列爲空的,從隊列中獲取元素的操作將會阻塞;

當隊列爲滿的,從隊列中添加元素的操作將會阻塞;

所謂的阻塞:在某些情況下會掛起線程(即阻塞),一旦條件滿足,被掛起的線程又會自動被喚起。

阻塞隊列的用處:不需要我們關心什麼時候需要阻塞線程,什麼時候需要喚醒線程。

BlockingQueue的實現類(比較常用):

  1. ArrayBlockingQueue:有數組結構組成的有界阻塞隊列;
  2. LinkedBlockingQueue:有鏈表結構組成的有界(但大小默認值爲Integer.MAX_VALUE)阻塞隊列;
  3. SynchronousQueue:不存儲元素的阻塞隊列,即單個元素的隊列。
方法類型 拋出異常 布爾值 阻塞 超時
插入 add(e) offer(e) put(e) offer(e,time,TimeUnit)
刪除 remove() poll() take() poll(time,TimeUnit);
檢查 element() peek() 不可用 不可用

拋出異常

  1. 當阻塞隊列滿時,再往隊列裏add插入元素會拋出IllegalStateException:Queue full
  2. 當隊列爲空時,再往隊列中remove移除元素會拋NoSuchElementException
ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(3);
System.out.println(queue.add("a"));
System.out.println(queue.add("a"));
System.out.println(queue.add("a"));

System.out.println(queue.remove());
System.out.println(queue.remove());
System.out.println(queue.remove());
System.out.println(queue.remove());

布爾值

  1. 插入方法,成功未true,失敗爲false
  2. 移除方法,成功返回隊列的元素,隊列沒有就返回null
System.out.println(queue.offer("a"));
System.out.println(queue.offer("a"));
System.out.println(queue.offer("a"));

System.out.println(queue.poll());
System.out.println(queue.poll());
System.out.println(queue.poll());
System.out.println(queue.poll());

阻塞

  1. 當阻塞隊列滿時,生產者線程繼續往隊列裏put元素,隊列會一直阻塞生產者線程直到put數據or響應中斷退出
  2. 當阻塞隊列空時,消費者線程試圖從隊列裏take元素,隊列會一直阻塞消費者線程直到隊列可用
queue.put("a");
queue.put("a");
queue.put("a");
//queue.put("a");
System.out.println(queue.take());
System.out.println(queue.take());
System.out.println(queue.take());
//System.out.println(queue.take());

超時

  1. 當阻塞隊列滿時,隊列會阻塞生產者線程一定時間,超過限制後生產者線程會退出
queue.offer("a");
queue.offer("a");
queue.offer("a");
queue.offer("a",1L, TimeUnit.SECONDS);

System.out.println(queue.poll());
System.out.println(queue.poll());
System.out.println(queue.poll());
queue.poll(1L,TimeUnit.SECONDS);

注意:

如果是無界阻塞隊列,隊列不可能會出現滿的情況,所以使用put或offer方法永遠不會被阻塞,而且使用offer方法時,該方法永遠返回true

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