哈嘍,各位小伙伴們,你們好呀,我是喵手。運營社區:C站/掘金/騰訊云;歡迎大家常來逛逛
??今天我要給大家分享一些自己日常學習到的一些知識點,并以文字的形式跟大家一起交流,互相學習,一個人雖可以走的更快,但一群人可以走的更遠。
??我是一名后端開發愛好者,工作日常接觸到最多的就是Java語言啦,所以我都盡量抽業余時間把自己所學到所會的,通過文章的形式進行輸出,希望以這種方式幫助到更多的初學者或者想入門的小伙伴們,同時也能對自己的技術進行沉淀,加以復盤,查缺補漏。
小伙伴們在批閱的過程中,如果覺得文章不錯,歡迎點贊、收藏、關注哦。三連即是對作者我寫作道路上最好的鼓勵與支持!
前言
??在軟件開發領域,隊列是一種非常重要的數據結構。它被廣泛應用于多線程、網絡通信、緩存、消息隊列等場景。Java語言提供了多種隊列實現,其中最常用的是Queue接口及其實現類。下面將詳細介紹Java中的Queue及其應用場景。
摘要
??本文將介紹Java中Queue接口及其實現類的概念、源代碼解析、應用場景案例、優缺點分析、類代碼方法介紹、測試用例等內容。原則上,讀者需要掌握Java基礎語法及數據結構相關知識。
Queue
簡介
??Queue是Java中的一種接口,它繼承自Collection接口,并添加了一些隊列相關的方法。Queue的實現類有多種,包括LinkedList、ArrayBlockingQueue、PriorityQueue、ConcurrentLinkedQueue等。下面簡要介紹一下各個實現類的特點:
- LinkedList
??LinkedList是Java中的一個雙向鏈表實現類。LinkedList實現了Deque接口,Deque又是Queue接口的子接口,因此LinkedList可以被視為Queue的一種實現。LinkedList的優點是插入、刪除操作效率高,但是隨機訪問效率低。
- ArrayBlockingQueue
??ArrayBlockingQueue是Java中的一個基于數組的有界阻塞隊列實現類。它的內部實現類似于一個環形數組,數組的長度是固定的。ArrayBlockingQueue具有先進先出的隊列特性,它支持多線程安全訪問,可以指定等待時間,當隊列滿或空時,線程將被阻塞。
- PriorityQueue
??PriorityQueue是Java中的一個帶優先級的隊列實現類。它的內部是一個堆結構,根據元素的排序規則進行排序,每次出隊時都會返回當前隊列中最小(或最大)的元素。PriorityQueue的特點是插入、刪除效率高,但是元素數量較大時遍歷效率不高。
- ConcurrentLinkedQueue
??ConcurrentLinkedQueue是Java中的一個基于鏈表的無界并發隊列實現類。ConcurrentLinkedQueue的特點是多線程安全,能夠高效地處理高并發場景。它不支持阻塞操作,而且不保證元素的排序。
源代碼解析
下面我們以ArrayBlockingQueue為例,簡單解析一下它的源代碼。
public class ArrayBlockingQueue<E> extends AbstractQueue<E>implements BlockingQueue<E>, java.io.Serializable {/** The queued items */final Object[] items;/** items index for next take, poll or remove */int takeIndex;/** items index for next put, offer, or add */int putIndex;/** Number of elements in the queue */int count;/** Main lock guarding all access */final ReentrantLock lock;/** Condition for waiting takes */private final Condition notEmpty;/** Condition for waiting puts */private final Condition notFull;// ...
}
??如上所示,ArrayBlockingQueue繼承了AbstractQueue類,并實現了BlockingQueue接口和Serializable接口。其內部使用了一個Object數組items用于存儲隊列中的元素,使用takeIndex和putIndex分別表示下一次取出元素和添加元素的位置,使用count表示隊列中當前元素個數,使用lock實現線程同步,使用notEmpty和notFull兩個Condition實現阻塞和喚醒操作。
如下是部分源碼截圖:
應用場景案例
下面介紹一下Queue在實際開發中的應用場景:
-
消息隊列
在分布式系統中,消息隊列是一種常用的通信方式。生產者向隊列中添加消息,消費者從隊列中取出消息進行處理。Java語言中提供的ActiveMQ和RabbitMQ等消息隊列服務均使用了隊列的相關技術。
-
線程池
在Java中,線程池通常使用BlockingQueue來存儲待執行的任務。當線程池中的線程已經全部分配任務時,新的任務將會被阻塞,直到有線程可用為止。Java中的ThreadPoolExecutor就是使用了BlockingQueue來存儲待執行的任務。
-
緩存
??在Java中,緩存通常使用LinkedList或ConcurrentLinkedQueue來實現。緩存存儲的是最近訪問過的元素,當緩存已滿時,新的元素會將最舊的元素移除。
優缺點分析
Queue的優缺點分析如下:
-
優點
Queue能夠高效地實現元素的插入、刪除以及元素的存儲。Queue還能夠在多線程場景中安全地實現元素的讀寫操作。
-
缺點
??在某些場景下,Queue可能會存在性能瓶頸。例如當Queue中元素數量較大時,遍歷操作效率較低,此時需要使用其他數據結構來優化性能。另外Queue中元素的順序是固定的,無法對元素的順序進行修改。
類代碼方法介紹
Queue接口中包含了很多常用的方法,下面介紹一下其中一些常用的方法:
-
add(E e)
將元素e添加到隊列尾部,如果隊列已滿,則拋出IllegalStateException異常。
-
offer(E e)
將元素e添加到隊列尾部,返回值表示添加操作是否成功。
-
remove()
移除隊列頭部的元素并返回該元素,如果隊列為空,則拋出NoSuchElementException異常。
-
poll()
移除隊列頭部的元素并返回該元素,如果隊列為空,則返回null。
-
element()
返回隊列頭部的元素,如果隊列為空,則拋出NoSuchElementException異常。
-
peek()
返回隊列頭部的元素,如果隊列為空,則返回null。
測試用例
下面給出ArrayBlockingQueue的測試用例:
測試代碼
package com.example.javase.collection;import java.util.concurrent.*;/*** @Author ms* @Date 2023-10-24 23:32*/
public class QueueTest {private static final int BUFFER_SIZE = 10;private static final int PRODUCER_COUNT = 5;private static final int CONSUMER_COUNT = 5;private static final int ITEM_COUNT = 1000;private static final ExecutorService pool = Executors.newCachedThreadPool();public static void main(String[] args) throws InterruptedException {ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(BUFFER_SIZE);for (int i = 0; i < PRODUCER_COUNT; i++) {pool.execute(new Producer(queue, ITEM_COUNT));}for (int i = 0; i < CONSUMER_COUNT; i++) {pool.execute(new Consumer(queue, ITEM_COUNT));}TimeUnit.SECONDS.sleep(60);pool.shutdown();}static class Producer implements Runnable {final BlockingQueue<Integer> queue;final int count;Producer(BlockingQueue<Integer> queue, int count) {this.queue = queue;this.count = count;}public void run() {try {for (int i = 0; i < count; i++) {queue.put(i);}} catch (InterruptedException e) {Thread.currentThread().interrupt();}}}static class Consumer implements Runnable {final BlockingQueue<Integer> queue;final int count;Consumer(BlockingQueue<Integer> queue, int count) {this.queue = queue;this.count = count;}public void run() {try {for (int i = 0; i < count; i++) {queue.take();}} catch (InterruptedException e) {Thread.currentThread().interrupt();}}}
}
??這段代碼實現了生產者-消費者模型,使用了Java內置的阻塞隊列ArrayBlockingQueue來作為共享的緩沖區。主要包含了三個部分:
-
定義了共享緩沖區的大小BUFFER_SIZE、生產者和消費者的數量PRODUCER_COUNT和CONSUMER_COUNT,以及需要生產和消費的數據ITEM_COUNT。
-
在main方法中,創建一個ArrayBlockingQueue實例,并分別創建PRODUCER_COUNT個生產者線程和CONSUMER_COUNT個消費者線程,然后分別啟動這些線程并等待60秒鐘后關閉線程池。
-
Producer和Consumer類都實現了Runnable接口。在Producer的run方法中,不斷向隊列中添加數據,直到添加的次數達到ITEM_COUNT;在Consumer的run方法中,不斷從隊列中取出數據,直到取出的次數達到ITEM_COUNT。由于ArrayBlockingQueue是線程安全的,因此不需要做額外的同步處理。
??總的來說,這段代碼展示了如何使用Java內置的阻塞隊列來實現生產者-消費者模型,避免了手動實現同步和互斥的復雜性,提高了代碼的可讀性、可維護性和可復用性。
測試結果
??根據如上測試用例,本地測試結果如下,僅供參考,你們也可以自行修改測試用例或者添加更多的測試數據或測試方法,進行熟練學習以此加深理解。
代碼分析
??根據如上測試用例,本地測試結果如下,僅供參考,你們也可以自行修改測試用例或者添加更多的測試數據或測試方法,進行熟練學習以此加深理解。
??該代碼是一個使用 ArrayBlockingQueue
實現的生產者-消費者模型的示例。包含一個主類 ArrayBlockingQueueTest 和兩個內部靜態類 Producer 和 Consumer。主類中創建一個 ArrayBlockingQueue
,然后創建 PRODUCER_COUNT
個 Producer
線程和 CONSUMER_COUNT
個 Consumer
線程,并啟動它們。每個 Producer 線程向隊列中插入 ITEM_COUNT
個元素,每個 Consumer
線程從隊列中取出 ITEM_COUNT
個元素。當所有線程運行完畢后,程序將等待 60 秒鐘,然后關閉線程池。
??Producer
和 Consumer
類實現了 Runnable 接口,分別包含一個 BlockingQueue
對象和一個 count 變量。在 run()
方法中,Producer 線程將元素插入隊列中,Consumer
線程從隊列中取出元素。如果隊列已滿(對于 Producer
)或者隊列為空(對于 Consumer
),線程會進入阻塞狀態。如果線程被中斷,則中斷狀態會被設置并退出線程。
??該示例使用了線程池來管理并發任務,增加效率。使用 ArrayBlockingQueue
實現了并發訪問控制,保證了線程安全。
小結
??Queue是Java中的一個接口,它的實現類包括LinkedList
、ArrayBlockingQueue
、PriorityQueue
、ConcurrentLinkedQueue
等。Queue
常用于消息隊列、線程池、緩存等場景。在使用Queue時需要注意線程安全性和性能問題。
總結
??本文介紹了Java中Queue接口及其實現類的概念、源代碼解析、應用場景案例、優缺點分析、類代碼方法介紹、測試用例等內容。Queue是Java中常用的數據結構,能夠高效地實現元素的插入、刪除及存儲,在多線程場景中也能保障線程安全。常用的Queue實現類有LinkedList、ArrayBlockingQueue、PriorityQueue、ConcurrentLinkedQueue等,它們都具有各自的優缺點。Queue的應用場景包括消息隊列、線程池、緩存等。在使用Queue時需要注意性能問題和線程安全性。
… …
文末
好啦,以上就是我這期的全部內容,如果有任何疑問,歡迎下方留言哦,咱們下期見。
… …
學習不分先后,知識不分多少;事無巨細,當以虛心求教;三人行,必有我師焉!!!
wished for you successed !!!
??若喜歡我,就請關注我叭。
??若對您有用,就請點贊叭。
??若有疑問,就請評論留言告訴我叭。