Java中常用的七種隊(duì)列

一、前言:

必看:https://mp.weixin.qq.com/s?__biz=MzU0OTE4MzYzMw==&mid=2247492750&idx=5&sn=63e28f968e1af536da39c69f48477833&chksm=fbb16d70ccc6e46672f565ef787bd67bf50df66a8a080e646aa02792e76944af60fb71a7467d&scene=27

1、什么是隊(duì)列?

隊(duì)列(Queue):是集合(Collection)的一個(gè)子類。隊(duì)列允許在一端進(jìn)行插入操作,而在另一端進(jìn)行刪除操作的線性表,而隊(duì)列的特點(diǎn)是先進(jìn)先出。隊(duì)列的用處很大,比如實(shí)現(xiàn)消息隊(duì)列。

注意:棧的特點(diǎn)是后進(jìn)先出。

Queue 類關(guān)系圖.png

從上圖可以看出 Queue 大體可分為以下三類。

  • 雙端隊(duì)列:雙端隊(duì)列(Deque)是 Queue 的子類也是 Queue 的補(bǔ)充類,頭部和尾部都支持元素插入和獲取。
  • 阻塞隊(duì)列:阻塞隊(duì)列指的是在元素操作時(shí)(添加或刪除),如果沒有成功,會阻塞等待執(zhí)行。例如,當(dāng)添加元素時(shí),如果隊(duì)列元素已滿,隊(duì)列會阻塞等待直到有空位時(shí)再插入。
  • 非阻塞隊(duì)列:非阻塞隊(duì)列和阻塞隊(duì)列相反,會直接返回操作的結(jié)果,而非阻塞等待。雙端隊(duì)列也屬于非阻塞隊(duì)列。

2、隊(duì)列的分類

隊(duì)列的分類.png
隊(duì)列名稱 底層數(shù)據(jù)結(jié)構(gòu) 是否有界 備注
ArrayBlockingQueue 數(shù)組 有界的 一個(gè)基于數(shù)組結(jié)構(gòu)的有界阻塞隊(duì)列,按照先進(jìn)先出的原則對元素進(jìn)行排序(初始化時(shí)指定隊(duì)列的大?。?。
LinkedBlockingQueue 鏈表 有界的 一個(gè)基于鏈表結(jié)構(gòu)的有界阻塞隊(duì)列,按照先進(jìn)先出的原則對元素進(jìn)行排序(默認(rèn)隊(duì)列大小Integer.MAX_VALUE)。
PriorityBlockingQueue 數(shù)組 無界的 一個(gè)支持優(yōu)先級排序的無界阻塞隊(duì)列(可以自定義比較器)。
DelayQueue 數(shù)組 無界的 一個(gè)支持延時(shí)獲取元素的無界阻塞隊(duì)列。
SynchronousQueue 鏈表 不存儲元素 一個(gè)不存儲元素的阻塞隊(duì)列,每個(gè)插入操作必須等待另一個(gè)線程的移除操作,否則插入操作一直處于阻塞狀態(tài)(同步的,一個(gè)offer必須與一個(gè)take與之相對應(yīng),否則放不了元素)。
LinkedTransferQueue 鏈表 無界的 一個(gè)基于鏈表結(jié)構(gòu)的無界阻塞隊(duì)列,支持生產(chǎn)者消費(fèi)者模式。
ConcurrentLinkedQueue 鏈表 無界的 一個(gè)基于鏈表結(jié)構(gòu)的無界并發(fā)隊(duì)列,按照先進(jìn)先出的原則對元素進(jìn)行排序(雙端數(shù)組隊(duì)列)。

3、什么時(shí)候使用隊(duì)列?

隊(duì)列是一種先進(jìn)先出(FIFO)的數(shù)據(jù)結(jié)構(gòu),通常適用于以下場景:

  • 1、處理大量的任務(wù)或請求:如果系統(tǒng)需要處理大量的任務(wù)或請求,并且需要保證這些任務(wù)或請求按照先來后到的順序依次處理,那么隊(duì)列數(shù)據(jù)結(jié)構(gòu)就可以發(fā)揮作用。比如,處理大量的網(wǎng)絡(luò)請求任務(wù)或消息處理。
  • 2、線程同步和通信:在多線程環(huán)境中,隊(duì)列可以用來進(jìn)行線程同步和通信。比如,線程池中的任務(wù)隊(duì)列,生產(chǎn)者-消費(fèi)者模型中的消息隊(duì)列等,可以把多個(gè)線程間的通信和同步問題簡單解決。
  • 3、消息中間件:隊(duì)列還常用于基于消息隊(duì)列的消息傳遞機(jī)制中,比如 ActiveMQ、RabbitMQ 等消息中間件,這些中間件的底層都實(shí)現(xiàn)了消息隊(duì)列的邏輯,允許生產(chǎn)者將消息放入隊(duì)列中,消費(fèi)者從隊(duì)列中拿到對應(yīng)的消息來處理。
  • 4、緩存:隊(duì)列還可以充當(dāng)緩存的角色,當(dāng)緩存滿時(shí),再來新的數(shù)據(jù)就可以利用隊(duì)列的原理,把最早的數(shù)據(jù)移出隊(duì)列,從而達(dá)到緩存數(shù)據(jù)的目的??傊?,隊(duì)列可以在許多領(lǐng)域和場景中找到應(yīng)用,特別是在處理和傳遞數(shù)據(jù)時(shí),可以通過隊(duì)列的先進(jìn)先出特性,簡單有效地實(shí)現(xiàn)多個(gè)任務(wù)、數(shù)據(jù)的異步處理和通信。

二、隊(duì)列的使用:

1、Queue 方法說明

Queue 常用方法,如下圖所示:


8c899bf7e9cf44721cbb8e1bd808eb3.png

方法說明:

  • add(E):添加元素到隊(duì)列尾部,成功返回 true,隊(duì)列超出時(shí)拋出異常;
  • offer(E):添加元素到隊(duì)列尾部,成功返回 true,隊(duì)列超出時(shí)返回 false;
  • remove():刪除元素,成功返回 true,失敗返回 false;
  • poll():獲取并移除此隊(duì)列的第一個(gè)元素,若隊(duì)列為空,則返回 null;
  • peek():獲取但不移除此隊(duì)列的第一個(gè)元素,若隊(duì)列為空,則返回 null;
  • element():獲取但不移除此隊(duì)列的第一個(gè)元素,若隊(duì)列為空,則拋異常。

2、Queue 使用實(shí)例

Queue<String> linkedList = new LinkedList<>();
linkedList.add("Dog");
linkedList.add("Camel");
linkedList.add("Cat");
while (!linkedList.isEmpty()) {
    System.out.println(linkedList.poll());
}

程序執(zhí)行結(jié)果

Dog
Camel
Cat

3、阻塞隊(duì)列

1、BlockingQueue

BlockingQueue 在 java.util.concurrent 包下,其他阻塞類都實(shí)現(xiàn)自 BlockingQueue 接口,BlockingQueue 提供了線程安全的隊(duì)列訪問方式,當(dāng)向隊(duì)列中插入數(shù)據(jù)時(shí),如果隊(duì)列已滿,線程則會阻塞等待隊(duì)列中元素被取出后再插入;當(dāng)從隊(duì)列中取數(shù)據(jù)時(shí),如果隊(duì)列為空,則線程會阻塞等待隊(duì)列中有新元素再獲取。

插入方法:

  • add(E):添加元素到隊(duì)列尾部,成功返回 true,隊(duì)列超出時(shí)拋出異常;
  • offer(E):添加元素到隊(duì)列尾部,成功返回 true,隊(duì)列超出時(shí)返回 false ;
  • put(E):將元素插入到隊(duì)列的尾部,如果該隊(duì)列已滿,則一直阻塞。

刪除方法:

  • remove(Object):移除指定元素,成功返回 true,失敗返回 false;
  • poll(): 獲取并移除隊(duì)列的第一個(gè)元素,如果隊(duì)列為空,則返回 null;
  • take():獲取并移除隊(duì)列第一個(gè)元素,如果沒有元素則一直阻塞。 檢查方法:
  • peek():獲取但不移除隊(duì)列的第一個(gè)元素,若隊(duì)列為空,則返回 null。

2、LinkedBlockingQueue

LinkedBlockingQueue 是一個(gè)由鏈表實(shí)現(xiàn)的有界阻塞隊(duì)列,容量默認(rèn)值為 Integer.MAX_VALUE,也可以自定義容量,建議指定容量大小,默認(rèn)大小在添加速度大于刪除速度情況下有造成內(nèi)存溢出的風(fēng)險(xiǎn),LinkedBlockingQueue 是先進(jìn)先出的方式存儲元素。

3、ArrayBlockingQueue

ArrayBlockingQueue 是一個(gè)有邊界的阻塞隊(duì)列,它的內(nèi)部實(shí)現(xiàn)是一個(gè)數(shù)組。它的容量是有限的,我們必須在其初始化的時(shí)候指定它的容量大小,容量大小一旦指定就不可改變。

ArrayBlockingQueue 也是先進(jìn)先出的方式存儲數(shù)據(jù),ArrayBlockingQueue 內(nèi)部的阻塞隊(duì)列是通過重入鎖 ReenterLock 和 Condition 條件隊(duì)列實(shí)現(xiàn)的,因此 ArrayBlockingQueue 中的元素存在公平訪問與非公平訪問的區(qū)別,對于公平訪問隊(duì)列,被阻塞的線程可以按照阻塞的先后順序訪問隊(duì)列,即先阻塞的線程先訪問隊(duì)列。而非公平隊(duì)列,當(dāng)隊(duì)列可用時(shí),阻塞的線程將進(jìn)入爭奪訪問資源的競爭中,也就是說誰先搶到誰就執(zhí)行,沒有固定的先后順序。

示例代碼如下:

// 默認(rèn)非公平阻塞隊(duì)列
ArrayBlockingQueue queue = new ArrayBlockingQueue(6);
// 公平阻塞隊(duì)列
ArrayBlockingQueue queue2 = new ArrayBlockingQueue(6,true);

// ArrayBlockingQueue 源碼展示
public ArrayBlockingQueue(int capacity) {
    this(capacity, false);
}
public ArrayBlockingQueue(int capacity, boolean fair) {
    if (capacity <= 0)
        throw new IllegalArgumentException();
    this.items = new Object[capacity];
    lock = new ReentrantLock(fair);
    notEmpty = lock.newCondition();
    notFull =  lock.newCondition();
}

4、DelayQueue

DelayQueue 是一個(gè)支持延時(shí)獲取元素的無界阻塞隊(duì)列,隊(duì)列中的元素必須實(shí)現(xiàn) Delayed 接口,在創(chuàng)建元素時(shí)可以指定延遲時(shí)間,只有到達(dá)了延遲的時(shí)間之后,才能獲取到該元素。

實(shí)現(xiàn)了 Delayed 接口必須重寫兩個(gè)方法 ,getDelay(TimeUnit) 和 compareTo(Delayed),如下代碼所示:

class DelayElement implements Delayed {
        @Override
        // 獲取剩余時(shí)間
        public long getDelay(TimeUnit unit) {
            // do something
        }
        @Override
        // 隊(duì)列里元素的排序依據(jù)
        public int compareTo(Delayed o) {
            // do something
        }
    }

DelayQueue 使用的完整示例 ,請參考以下代碼:

public  class DelayTest {
    public static void main(String[] args) throws InterruptedException {
        DelayQueue delayQueue = new DelayQueue();
        delayQueue.put(new DelayElement(1000));
        delayQueue.put(new DelayElement(3000));
        delayQueue.put(new DelayElement(5000));
        System.out.println("開始時(shí)間:" +  DateFormat.getDateTimeInstance().format(new Date()));
        while (!delayQueue.isEmpty()){
            System.out.println(delayQueue.take());
        }
        System.out.println("結(jié)束時(shí)間:" +  DateFormat.getDateTimeInstance().format(new Date()));
    }

    static class DelayElement implements Delayed {
        // 延遲截止時(shí)間(單面:毫秒)
        long delayTime = System.currentTimeMillis();
        public DelayElement(long delayTime) {
            this.delayTime = (this.delayTime + delayTime);
        }
        @Override
        // 獲取剩余時(shí)間
        public long getDelay(TimeUnit unit) {
            return unit.convert(delayTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
        }
        @Override
        // 隊(duì)列里元素的排序依據(jù)
        public int compareTo(Delayed o) {
            if (this.getDelay(TimeUnit.MILLISECONDS) > o.getDelay(TimeUnit.MILLISECONDS)) {
                return 1;
            } else if (this.getDelay(TimeUnit.MILLISECONDS) < o.getDelay(TimeUnit.MILLISECONDS)) {
                return -1;
            } else {
                return 0;
            }
        }
        @Override
        public String toString() {
            return DateFormat.getDateTimeInstance().format(new Date(delayTime));
        }
    }
}

程序執(zhí)行結(jié)果:

開始時(shí)間:2019-6-13 20:40:38
2019-6-13 20:40:39
2019-6-13 20:40:41
2019-6-13 20:40:43
結(jié)束時(shí)間:2019-6-13 20:40:43

4、非阻塞隊(duì)列

1、ConcurrentLinkedQueue

ConcurrentLinkedQueue 是一個(gè)基于鏈接節(jié)點(diǎn)的無界線程安全隊(duì)列,它采用先進(jìn)先出的規(guī)則對節(jié)點(diǎn)進(jìn)行排序,當(dāng)我們添加一個(gè)元素的時(shí)候,它會添加到隊(duì)列的尾部;當(dāng)我們獲取一個(gè)元素時(shí),它會返回隊(duì)列頭部的元素。

它的入隊(duì)和出隊(duì)操作均利用 CAS(Compare And Set)更新,這樣允許多個(gè)線程并發(fā)執(zhí)行,并且不會因?yàn)榧渔i而阻塞線程,使得并發(fā)性能更好。

ConcurrentLinkedQueue 使用示例:

ConcurrentLinkedQueue concurrentLinkedQueue = new ConcurrentLinkedQueue();
concurrentLinkedQueue.add("Dog");
concurrentLinkedQueue.add("Cat");
while (!concurrentLinkedQueue.isEmpty()) {
    System.out.println(concurrentLinkedQueue.poll());
}

執(zhí)行結(jié)果:

Dog
Cat

可以看出不管是阻塞隊(duì)列還是非阻塞隊(duì)列,使用方法都是類似的,區(qū)別是底層的實(shí)現(xiàn)方式。

5、優(yōu)先級隊(duì)列

1、PriorityQueue

PriorityQueue 一個(gè)基于優(yōu)先級堆的無界優(yōu)先級隊(duì)列。優(yōu)先級隊(duì)列的元素按照其自然順序進(jìn)行排序,或者根據(jù)構(gòu)造隊(duì)列時(shí)提供的 Comparator 進(jìn)行排序,具體取決于所使用的構(gòu)造方法。優(yōu)先級隊(duì)列不允許使用 null 元素。

PriorityQueue 代碼使用示例 :

Queue<Integer> priorityQueue = new PriorityQueue(new Comparator<Integer>() {
    @Override
    public int compare(Integer o1, Integer o2) {
        // 非自然排序,數(shù)字倒序
        return o2 - o1;
    }
});
priorityQueue.add(3);
priorityQueue.add(1);
priorityQueue.add(2);
while (!priorityQueue.isEmpty()) {
    Integer i = priorityQueue.poll();
    System.out.println(i);
}

程序執(zhí)行的結(jié)果是

3
2
1

PriorityQueue 注意的點(diǎn) :

PriorityQueue 是非線程安全的,在多線程情況下可使用 PriorityBlockingQueue 類替代;PriorityQueue 不允許插入 null 元素。

三、相關(guān)面試題:

1、ArrayBlockingQueue 和 LinkedBlockingQueue 的區(qū)別是什么?

答:ArrayBlockingQueue 和 LinkedBlockingQueue 都實(shí)現(xiàn)自阻塞隊(duì)列 BlockingQueue,它們的區(qū)別主要體現(xiàn)在以下幾個(gè)方面:

  • ArrayBlockingQueue 使用時(shí)必須指定容量值,LinkedBlockingQueue 可以不用指定;
  • ArrayBlockingQueue 的最大容量值是使用時(shí)指定的,并且指定之后就不允許修改;而 LinkedBlockingQueue 最大的容量為 Integer.MAX_VALUE;
  • ArrayBlockingQueue 數(shù)據(jù)存儲容器是采用數(shù)組存儲的;而 LinkedBlockingQueue 采用的是 Node 節(jié)點(diǎn)存儲的。

2、LinkedList 中 add() 和 offer() 有什么關(guān)系?

答:add() 和 offer() 都是添加元素到隊(duì)列尾部。offer 方法是基于 add 方法實(shí)現(xiàn)的,Offer 的源碼如下:

public boolean offer(E e) {
    return add(e);
}

3、Queue 和 Deque 有什么區(qū)別?

答:Queue 屬于一般隊(duì)列,Deque 屬于雙端隊(duì)列。一般隊(duì)列是先進(jìn)先出,也就是只有先進(jìn)的才能先出;而雙端隊(duì)列則是兩端都能插入和刪除元素。

4、LinkedList 屬于一般隊(duì)列還是雙端隊(duì)列?

答:LinkedList 實(shí)現(xiàn)了 Deque 屬于雙端隊(duì)列,因此擁有 addFirst(E)、addLast(E)、getFirst()、getLast() 等方法。

5、以下說法錯(cuò)誤的是?

A:DelayQueue 內(nèi)部是基于 PriorityQueue 實(shí)現(xiàn)的
B:PriorityBlockingQueue 不是先進(jìn)先出的數(shù)據(jù)存儲方式
C:LinkedBlockingQueue 默認(rèn)容量是無限大的
D:ArrayBlockingQueue 內(nèi)部的存儲單元是數(shù)組,初始化時(shí)必須指定隊(duì)列容量

答:C
題目解析:LinkedBlockingQueue 默認(rèn)容量是 Integer.MAX_VALUE,并不是無限大的。

6、.關(guān)于 ArrayBlockingQueue 說法不正確的是?

A:ArrayBlockingQueue 是線程安全的
B:ArrayBlockingQueue 元素允許為 null
C:ArrayBlockingQueue 主要應(yīng)用場景是“生產(chǎn)者-消費(fèi)者”模型
D:ArrayBlockingQueue 必須顯示地設(shè)置容量

答:B

題目解析:ArrayBlockingQueue 不允許元素為 null,如果添加一個(gè) null 元素,會拋 NullPointerException 異常。

7、以下程序執(zhí)行的結(jié)果是什么?

PriorityQueue priorityQueue = new PriorityQueue();
priorityQueue.add(null);
System.out.println(priorityQueue.size());

答:程序執(zhí)行報(bào)錯(cuò),PriorityQueue 不能插入 null。

8、Java 中常見的阻塞隊(duì)列有哪些?

答:Java 中常見的阻塞隊(duì)列如下:

  • ArrayBlockingQueue,由數(shù)組結(jié)構(gòu)組成的有界阻塞隊(duì)列;
  • PriorityBlockingQueue,支持優(yōu)先級排序的無界阻塞隊(duì)列;
  • SynchronousQueue,是一個(gè)不存儲元素的阻塞隊(duì)列,會直接將任務(wù)交給消費(fèi)者,必須等隊(duì)列中的添加元素被消費(fèi)后才能繼續(xù)添加新的元素;
  • LinkedBlockingQueue,由鏈表結(jié)構(gòu)組成的阻塞隊(duì)列;DelayQueue,支持延時(shí)獲取元素的無界阻塞隊(duì)列。

9、有界隊(duì)列和無界隊(duì)列有哪些區(qū)別?

答:有界隊(duì)列和無界隊(duì)列的區(qū)別如下。

  • 有界隊(duì)列:有固定大小的隊(duì)列叫做有界隊(duì)列,比如:new ArrayBlockingQueue(6),6 就是隊(duì)列的大小。
  • 無界隊(duì)列:指的是沒有設(shè)置固定大小的隊(duì)列,這些隊(duì)列的特點(diǎn)是可以直接入列,直到溢出。它們并不是真的無界,它們最大值通常為 Integer.MAX_VALUE,只是平常很少能用到這么大的容量(超過 Integer.MAX_VALUE),因此從使用者的體驗(yàn)上,就相當(dāng)于 “無界”。

10、如何手動實(shí)現(xiàn)一個(gè)延遲消息隊(duì)列?

答:說到延遲消息隊(duì)列,我們應(yīng)該可以第一時(shí)間想到要使用 DelayQueue 延遲隊(duì)列來解決這個(gè)問題。實(shí)現(xiàn)思路,消息隊(duì)列分為生產(chǎn)者和消費(fèi)者,生產(chǎn)者用于增加消息,消費(fèi)者用于獲取并消費(fèi)消息,我們只需要生產(chǎn)者把消息放入到 DelayQueue 隊(duì)列并設(shè)置延遲時(shí)間,消費(fèi)者循環(huán)使用 take() 阻塞獲取消息即可。完整的實(shí)現(xiàn)代碼如下:

public class CustomDelayQueue {
    // 消息編號
    static AtomicInteger MESSAGENO = new AtomicInteger(1);

    public static void main(String[] args) throws InterruptedException {
        DelayQueue<DelayedElement> delayQueue = new DelayQueue<>();
        // 生產(chǎn)者1
        producer(delayQueue, "生產(chǎn)者1");
        // 生產(chǎn)者2
        producer(delayQueue, "生產(chǎn)者2");
        // 消費(fèi)者
        consumer(delayQueue);
    }

    //生產(chǎn)者
    private static void producer(DelayQueue<DelayedElement> delayQueue, String name) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    // 產(chǎn)生 1~5 秒的隨機(jī)數(shù)
                    long time = 1000L * (new Random().nextInt(5) + 1);
                    try {
                        Thread.sleep(time);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    // 組合消息體
                    String message = String.format("%s,消息編號:%s 發(fā)送時(shí)間:%s 延遲:%s 秒",
                            name, MESSAGENO.getAndIncrement(), DateFormat.getDateTimeInstance().format(new Date()), time / 1000);
                    // 生產(chǎn)消息
                    delayQueue.put(new DelayedElement(message, time));
                }
            }
        }).start();
    }

    //消費(fèi)者
    private static void consumer(DelayQueue<DelayedElement> delayQueue) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    DelayedElement element = null;
                    try {
                        // 消費(fèi)消息
                        element = delayQueue.take();
                        System.out.println(element);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

    // 延遲隊(duì)列對象
    static class DelayedElement implements Delayed {
        // 過期時(shí)間(單位:毫秒)
        long time = System.currentTimeMillis();
        // 消息體
        String message;
        // 參數(shù):delayTime 延遲時(shí)間(單位毫秒)
        public DelayedElement(String message, long delayTime) {
            this.time += delayTime;
            this.message = message;
        }
        @Override
        // 獲取過期時(shí)間
        public long getDelay(TimeUnit unit) {
            return unit.convert(time - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
        }
        @Override
        // 隊(duì)列元素排序
        public int compareTo(Delayed o) {
            if (this.getDelay(TimeUnit.MILLISECONDS) > o.getDelay(TimeUnit.MILLISECONDS))
                return 1;
            else if (this.getDelay(TimeUnit.MILLISECONDS) < o.getDelay(TimeUnit.MILLISECONDS))
                return -1;
            else
                return 0;
        }
        @Override
        public String toString() {
            // 打印消息
            return message + " |執(zhí)行時(shí)間:" + DateFormat.getDateTimeInstance().format(new Date());
        }
    }
}

以上程序支持多生產(chǎn)者,執(zhí)行的結(jié)果如下:

生產(chǎn)者1,消息編號:1 發(fā)送時(shí)間:2019-6-12 20:38:37 延遲:2 秒 |執(zhí)行時(shí)間:2019-6-12 20:38:39
生產(chǎn)者2,消息編號:2 發(fā)送時(shí)間:2019-6-12 20:38:37 延遲:2 秒 |執(zhí)行時(shí)間:2019-6-12 20:38:39
生產(chǎn)者1,消息編號:3 發(fā)送時(shí)間:2019-6-12 20:38:41 延遲:4 秒 |執(zhí)行時(shí)間:2019-6-12 20:38:45
生產(chǎn)者1,消息編號:5 發(fā)送時(shí)間:2019-6-12 20:38:43 延遲:2 秒 |執(zhí)行時(shí)間:2019-6-12 20:38:45
......

11、總結(jié):

  • 隊(duì)列(Queue)按照是否阻塞可分為:阻塞隊(duì)列 BlockingQueue 和 非阻塞隊(duì)列。
  • 其中,雙端隊(duì)列 Deque 也屬于非阻塞隊(duì)列,雙端隊(duì)列除了擁有隊(duì)列的先進(jìn)先出的方法之外,還擁有自己獨(dú)有的方法,如 addFirst()、addLast()、getFirst()、getLast() 等,支持首未插入和刪除元素。
  • 隊(duì)列中比較常用的兩個(gè)隊(duì)列還有 PriorityQueue(優(yōu)先級隊(duì)列)和 DelayQueue(延遲隊(duì)列),可使用延遲隊(duì)列來實(shí)現(xiàn)延遲消息隊(duì)列,這也是面試中比較常考的問題之一。

參考地址1:https://zhuanlan.zhihu.com/p/510794870?utm_id=0

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容