Java queue隊列接口指南

1.簡介

在本教程中,我們將討論Java的Queue接口。

首先,我們看看**Queue的功能及其一些核心方法。接下來,我們將深入研究Java作為標準提供的許多實現。

最後,在將其全部包裝之前,我們將討論線程安全性。

2.可視化隊列

讓我們從一個快速的類比開始。

想像一下,我們剛開始我們的第一筆生意–熱狗攤。我們希望以最有效的方式為我們的小型企業服務新的潛在客戶;一次一個。首先,我們要求他們在我們的展位前排成一排,在後方加入新客戶。由於我們的組織能力,我們現在可以公平地分配美味的熱狗了。

Java中的隊列以類似的方式工作。聲明隊列後,我們可以在後面添加新元素,並從前面刪除它們。

實際上,我們在Java中遇到的大多數隊列都是以這種先進先出的方式工作的-通常縮寫為FIFO。

但是,有一個例外情況我們稍後會介紹。

3.核心方法

隊列聲明了所有實現類都需要編碼的許多方法現在讓我們概述一些更重要**的:**

  1. offer() –在隊列中插入一個新元素
  2. poll() –從隊列的前面刪除一個元素
  3. *peek()檢查隊列前面的元素,*而不刪除它

4.抽象隊列

AbstractQueueJava提供最簡單的Queue實現。*它包括一些Queue接口方法的基本實現,但不包括offer* 。

當我們創建擴展AbstractQueue的定制隊列**我們必須提供**報價方法,不允許null元素插入**實現**。

另外,我們必須提供方法peek,poll,sizejava.utiliterator

讓我們使用AbstractQueue**組合一個簡單的Queue實現**

首先,讓我們用LinkedList定義我們的類,以存儲隊列的元素:

public class CustomBaeldungQueue<T> extends AbstractQueue<T> {



 private LinkedList<T> elements;



 public CustomBaeldungQueue() {

 this.elements = new LinkedList<T>();

 }



 }

接下來,讓我們重寫所需的方法並提供代碼:

@Override

 public Iterator<T> iterator() {

 return elements.iterator();

 }



 @Override

 public int size() {

 return elements.size();

 }



 @Override

 public boolean offer(T t) {

 if(t == null) return false;

 elements.add(t);

 return true;

 }



 @Override

 public T poll() {

 Iterator<T> iter = elements.iterator();

 T t = iter.next();

 if(t != null){

 iter.remove();

 return t;

 }

 return null;

 }



 @Override

 public T peek() {

 return elements.getFirst();

 }

太好了,讓我們檢查一下它是否可以用於快速的單元測試:

customQueue.add(7);

 customQueue.add(5);



 int first = customQueue.poll();

 int second = customQueue.poll();



 assertEquals(7, first);

 assertEquals(5, second);

4.子接口

通常, Queue接口由3個主要子接口繼承*。**阻塞隊列,傳輸隊列雙端*隊列

這3個接口一起由Java的絕大多數可用隊列實現。讓我們快速看一下這些接口的作用。

4.1。阻塞隊列

BlockingQueue接口支持其他操作,這些操作強制線程根據當前狀態在**隊列等待嘗試進行檢索時,線程可以等待Queue為非空,或者在添加新元素時使其變為空

標準阻塞隊列包括LinkedBlockingQueue,SynchronousQueueArrayBlockingQueue

有關更多信息,請轉至我們關於阻塞隊列的文章。

4.2。傳輸隊列

TransferQueue接口擴展了BlockingQueue接口,但針對生產者-消費者模式進行了定制。它控制從生產者到消費者的信息流,從而在系統中造成背壓。

Java附帶了TransferQueue接口的一種實現LinkedTransferQueue。

4.3。雙端隊列

雙端隊列為短於d ouble-Ënded***闕UE和類似於一副牌-元素可以從一開始就與雙端隊列的端兩者作出。就像傳統的Queue一樣,* **Deque提供了一些方法來添加,檢索和查看頂部和底部的元素

有關Deque如何工作的詳細指南,請查看我們的ArrayDeque文章。

5.優先隊列

前面我們看到,Java中遇到的大多數隊列都遵循FIFO原則。

PriorityQueue是此規則的一種例外。將新元素插入到Priority Queue中時,它們將根據其自然順序或在構造Priority Queue時提供的已定義Comparator進行排序

讓我們看一下如何使用簡單的單元測試:

PriorityQueue<Integer> integerQueue = new PriorityQueue<>();



 integerQueue.add(9);

 integerQueue.add(2);

 integerQueue.add(4);



 int first = integerQueue.poll();

 int second = integerQueue.poll();

 int third = integerQueue.poll();



 assertEquals(2, first);

 assertEquals(4, second);

 assertEquals(9, third);

儘管將整數添加到Priority Queue**的順序有所不同,但我們可以看到,檢索順序根據數字的自然順序而改變。**

我們可以看到,將其應用於String時也是如此:

PriorityQueue<String> stringQueue = new PriorityQueue<>();



 stringQueue.add("blueberry");

 stringQueue.add("apple");

 stringQueue.add("cherry");



 String first = stringQueue.poll();

 String second = stringQueue.poll();

 String third = stringQueue.poll();



 assertEquals("apple", first);

 assertEquals("blueberry", second);

 assertEquals("cherry", third);

6.線程安全

在多線程環境中,將項目添加到隊列特別有用。**隊列可以在線程之間共享,並且可以用來阻塞進度,直到空間可用為止–幫助我們克服了一些常見的多線程問題。**

例如,從多個線程寫入單個磁盤會造成資源爭用,並可能導致寫入時間變慢。使用BlockingQueue創建單個編寫器線程可以緩解此問題,並大大提高寫入速度。

幸運的是,Java提供了ConcurrentLinkedQueue,ArrayBlockingQueueConcurrentLinkedDeque ,它們是線程安全的,並且非常適合多線程程序。

7.結論

在本教程中,我們深入研究了Java Queue接口。

首先,我們探討了Queue的功能以及Java提供實現。

接下來,我們研究了Queue的通常FIFO原理以及PriorityQueue的順序不同。

最後,我們探討了線程安全性以及如何在多線程環境中使用隊列

與往常一樣,代碼可以 在GitHub上獲得