Java中常用隊列的總結

2020-12-18 凱哥Java

Java隊列總結

通過前面文章的學習,我們對Java中常用隊列做了介紹。本文,咱們來對隊列做個總結吧。

首先,我們介紹了現實生活中的實際場景(排隊買票等),來告訴我們為什麼需要使用隊列。

隊列是一種先進先出(FIFO)的抽象數據結構,在Java中,隊列使用了兩種數據類型來實現的,分別是:數組和鍊表這兩種數據結構。

本文主要內容:回顧Java中常用的七個阻塞隊列進行總結及阻塞隊列中四組AP並進行總結。

本文來源:本文是由凱哥Java(kaigejava)原創發布。

接著,我們介紹了隊列的分類,可以分為兩類,即阻塞隊列和非阻塞隊列。

常用的三個非阻塞隊列:LinkedList、PriorityQueue和ConcurrentLinkedQueue.

(PS:凱哥沒有做介紹,在以後的文章中,凱哥將對ConcurrentLinkedQueue進行介紹)

然後我們介紹Java中常用的七個阻塞隊列。他們之間類圖關係:

我們可以看到,隊列是Collection的子類。也即和arrayList類似的。

接著我們就對七個阻塞隊列做了詳細的介紹。

阻塞隊列的七個子類

ArrayBlockingQueue(下文簡稱:ABQueue)、LinkedBlockingQueue(下文簡稱:LBQueue)、PriorityBlockingQueue(下文簡稱:PBQueue)、DelayQueue(下文簡稱:DQueue)、SynchronouseQueue(下文簡稱:SyncQueue)、LinkedTrnsferQueue(下文簡稱:LTQueue)、LinkedBlockingDeque(下文簡稱:LBDeque)這個七個。

來分別說說每個隊列的特點:

ABQueue:

底層使用的是數組結構。因為數組需要初始化大小,所以其構造器需要輸入隊列的大小。

是有界的阻塞安全隊列(思考:為什麼說是有界的?是怎麼保證線程安全的?),默認是不保證線程的公平性(思考:為什麼默認不能保證線程公平?如何保證線程安全?),不允許向隊列中插入null元素。

LBQueue:

「有界」的阻塞安全隊列,其底層使用的是鍊表的數據結構。所謂的「有界」是因為,默認隊列的大小是Integer.MAX_VALUE。這個數值等於21億+。因為這個數據太大了,也可以理解為無界的。不建議使用默認值,最好在初始化的時候,指定隊列的大小。

PBQueue:

是一個支持優先級的無界隊列。支持優先級是因為使用了comparator這個接口。默認採用字典升序排序策略的。如果不想使用默認的,在初始化的時候,還可以自定義比較器的。

以上三個隊列相關更詳細的介紹,歡迎回看《Java中常用的七個阻塞隊列介紹第一篇》。在這篇文章中,凱哥對這三個隊列做了詳細的介紹以及代碼演示。

DQueue:

是一個支持優先級的無界阻塞隊列。支持優先級是應該底層使用的是PriorityQueue隊列來實現的。而PriorityQueue隊列在添加元素的時候使用了siftUpComparable方法。這個對了的一個特點:支持延時獲取。所以,這個隊列可以運用在緩存系統的設計中。當從隊列中獲取到數據,說明延時時間到了。

關於DQueue更多詳細的介紹,歡迎回看:《Java中常用的七個阻塞隊列第二篇DelayQueue源碼介紹》。在這篇文章中,凱哥做了詳細的介紹,同時使用代碼模擬了緩存數據到期操作。

SyncQueue:

是一個無存儲空間的阻塞同步隊列。不存儲元素的原因是因為,一個put操作必須等待一個take操作與之對應才可以。否則就不能繼續添加元素了。默認使用非公平的。在性能上SyncQueue隊列的吞吐量比LBqueu和ABQueue的性能高。

LTQueue:是由鍊表組成的無界隊列。比其他隊列多了兩個方法:tryTransfer、transfer

LBDeque:鍊表組成的雙端隊列。這個隊列在以後凱哥講For/Join框架的時候,還會說到。

七個阻塞隊列的小總結:

接著,我們講解了隊列中常用的四組API。

阻塞隊列四組API

會拋異常的:添加元素使用add(e),刪除元素使用remove,檢查隊首元素使用的element.

當隊列滿的時候,在向隊列中添加元素會拋出異常;當隊列為空的時候在從隊列中刪除或者是獲取隊首元素都會拋出異常;

帶有返回值的:添加元素:offer(e),刪除元素:poll(),檢查隊首元素:peek().

當隊列滿的時候,再調用offer(e)向隊列中添加元素會返回false而不是拋出異常

當隊列為空的時候,調用take()或者是peek()方法返回null而不是拋出異常

阻塞一直等待的:添加元素:put(e),刪除元素:take()

當隊列滿的時候,再向隊列中添加元素,隊列會進入阻塞狀態,直到元素添加成功為止。

當隊列為空的時候,再從隊列刪除元素,隊列會阻塞,直到能夠刪除元素為止。

帶有超時時間的阻塞:添加元素:offer(e,time,unit),刪除元素:poll(time,unit)

當隊列滿的時候,調用offer(e,time,unit)會進入阻塞等待中,當過來超時時間,退出等待

當隊列為空的時候,調用poll(time,unit)方法會進入等待狀態,當到了超時時間,會退出等待。

四組API總結:

關於四組API更詳細的介紹歡迎學習:《Java阻塞隊列的四組API》。在這篇文章中凱哥做了詳細的介紹。用人的一生四個階段來比擬這四組API。

到此,我們已經把Java中隊列介紹完畢。接下來,凱哥將帶著大家一起學習線程池。歡迎大家繼續學習。

相關焦點

  • 2020學習Java必看的3本書籍
    《Effective Java》本書一共包含90個條目,每個條目討論Java程序設計中的一條規則。這些規則反映了最有經驗的優秀程式設計師在實踐中常用的一些有益的做法。本書的目標是幫助讀者更加有效地使用Java程式語言及其基本類庫:java.lang、java.util和java.io,以及子包,如java.util.concurrent和java.util.function。本書時不時地也會討論其他的類庫。3.
  • java基礎教程:Collection集合,Collection 常用API
    集合:集合是java中提供的一種容器,可以用來存儲多個數據。集合和數組既然都是容器,它們有什麼區別呢?數組的長度是固定的。集合的長度是可變的。集合常用類的繼承體系Collection:單列集合類的根接口,用於存儲一系列符合某種規則的元素,它有兩個重要的子接口,分別是java.util.List和java.util.Set。其中,List的特點是元素有序、元素可重複。Set的特點是元素不可重複。
  • Java異常的十大問題總結
    本文總結了有關Java異常的十大常見問題。1.已檢查與未檢查簡而言之,必須在方法中顯式捕獲已檢查的異常或在方法的throws子句中聲明該異常。3.為什麼在try中定義的變量不能被catch或final使用?在以下代碼中,在try塊中聲明的字符串s不能在catch子句中使用。該代碼不通過編譯。原因是您不知道在try塊中的哪個位置會引發異常。很有可能在聲明對象之前引發了異常。
  • java中為什麼不推薦使用finalize,知道原因後相信你也不會用了
    java提供了一個finalize方法,可以幫助我們進行資源釋放,類似於C++中的析構函數。但是目前普遍的認識是不要使用,為什麼呢?就是因為對java虛擬機的垃圾回收有影響。這篇文章對其進行一個說明。java虛擬機在進行垃圾回收的時候,一看到這個對象類含有finalize函數,就把這個函數交給FinalizerThread處理,而包含了這個finalize的對象就會被添加到FinalizerThread的執行隊列,並使用一個鍊表,把這些包含了finalize的對象串起來。
  • 用兩個棧實現隊列(劍指 Offer 題解Java版)
    分析棧的特點是先進後出,而隊列的特點是先進先出,主要就是在兩個棧中來回倒騰從而實現隊列的功能,就好像一個黑盒子,裡邊是兩個棧的操作,但其他人在用這個黑盒子的時候,感覺就像在用隊列一樣。隊列和棧只是邏輯性的數據結構,實現隊列和棧可以用數組實現,也可以用鍊表實現,只要滿足隊列先進先出,棧先進後出的特性就可以。
  • java集合詳解合集
    所以的集合類都位於java.util包下,後來為了處理多線程環境下的並發安全問題,java5還在java.util.concurrent包下提供了一些多線程支持的集合類。在學習Java中的集合類的API、編程原理的時候,我們一定要明白,"集合"是一個很古老的數學概念,它遠遠早於Java的出現。
  • java線程池核心類ThreadPoolExecutor概述
    前言前文JAVA中的阻塞隊列和非阻塞隊列我們介紹了常用的幾種隊列,隊列的使用很廣泛,特別是一些需要生產消費模式的場景以及需要對全局的集合進行操作的場景。今天我們來講講其中的一種應用——線程池。核心類在java.util.concurrent包中我們能找到線程池的定義,其中ThreadPoolExecutor是我們線程池的核心類,我們先看下構造函數。
  • 結合JAVA詳解鍊表、棧、隊列等數據結構
    總結順序表最大的特點是:查詢快,因為是數組,直接下標出。插入和移除就比較慢了。這些方法中的每一種都有兩種形式:如果操作失敗,則拋出一個異常,另一種返回一個特殊值(null或false,具體取決於操作)。
  • 詳解SpringCloud中RabbitMQ消息隊列原理及配置,一篇就夠!
    Producer發送消息到RabbitMQ中,MQ中的Direct交換器接受到消息後,會根據Routing Key來決定這個消息要發送到哪一個隊列中。Consumer則負責註冊一個隊列監聽器,來監聽隊列的狀態,當隊列狀態發生變化時,消費消息。註冊隊列監聽需要提供交換器信息,隊列信息和路由鍵信息。這種交換器通常用於點對點消息傳輸的業務模型中。如電子郵箱。
  • Java基礎面試題簡單總結
    中的保留字,現在沒有在java中使用11、數組有沒有length()這個方法?48、一個".java"源文件中是否可以包括多個類(不是內部類)?有什麼限制? 答:可以。必須只有一個類名與文件名相同。49、java中有幾種類型的流?
  • 「原創」Java並發編程系列29|ConcurrentLinkedQueue
    本文轉載自【微信公眾號:java進階架構師,ID:java_jiagoushi】經微信公眾號授權轉載,如需轉載與原文作者聯繫J.U.C 為常用的集合提供了並發安全的版本,前面講解了 map 的並發安全集合 ConcurrentHashMap,List 並發安全集合 CopyOnWriteArrayList,Set 並發安全集合
  • Java面試總結之Full GC
    通常我們所說的gc主要是針對java heap這塊區域的。下面來了解一下heap區。從圖中我們可以看出jvm heap區域是分代的,分為年輕代,老年代和持久代。 JVM的堆區對象分配的一般規則:1. 對象優先在Eden區分配2.
  • 基礎不牢地動山搖記住 Java 面試中常用的八種排序算法與代碼實現
    本文轉載自【微信公眾號:java進階架構師,ID:java_jiagoushi】經微信公眾號授權轉載,如需轉載與原文作者聯繫1.直接插入排序經常碰到這樣一類排序問題:把新的數據插入到已經排好的數據列中。
  • 2020年的Java程式設計師面試三件套:多線程+算法+微服務
    可以毫不誇張地說,多線程是開發人員在繼續「升級」的過程中必須打倒的一隻「怪物」。「設計模式」一詞也常常會讓開發人員感到畏懼。其實設計模式不過是對代碼設計方式的總結和歸納。在我們的代碼中,設計模式無處不在,只是我們沒有注意到它們而已。善用設計模式可以幫助我們編寫出具有高可復用性且鬆耦合的代碼。
  • 三萬字總結最全Java線程池源碼面試題
    1、線程在java中是一個對象,更是作業系統的資源,線程創建、銷毀都需要時間。如果創建時間+銷毀時間>執行任務時間就很不合算。2、Java對象佔用堆內存,作業系統線程佔用系統內存,根據JVM規範,一個線程默認最大棧大小1M,這個棧空間是需要從系統內存中分配的。線程過多,會消耗很多的內存。
  • Java並發編程系列21|Condition-Lock的等待通知
    本文轉載自【微信公眾號:java進階架構師,ID:java_jiagoushi】經微信公眾號授權轉載,如需轉載與原文作者聯繫我們知道 synchronized 鎖通過 Object 類的 wait()和 notify()方法實現線程間的等待通知機制,而比 synchronized 更靈活 Lock 鎖同樣也有實現等待通知機制的方式
  • java集合之LinkedList源碼分析
    一、查看類的繼承關係關於Cloneable,java.io.Serializable兩個接口和為什麼沒有實現RandomAccess接口,我們上次已經說過了,如果不是很理解,請參考上一篇文章:《java集合之ArrayList源碼分析》這次重點把LinkedList源碼看一遍先簡單說明:LinkedList 內部是一個鍊表LinkedList首先會繼承AbstractSequentialList
  • java是什麼文件格式?.java文件怎麼打開?
    java是什麼文件?  Java文件是由Sun Microsystems公司於1995年5月推出的Java程序設計語言和Java平臺的總稱。用Java實現的HotJava瀏覽器(支持Java applet)顯示了Java的魅力:跨平臺、動態的Web、Internet計算。從此,Java被廣泛接受並推動了Web的迅速發展,常用的瀏覽器現在均支持Java applet。
  • Java實現冒泡排序算法
    、與常用算法#學習內容:1.數據結構的定義2.算法的定義3.複雜度分析4.常用數據結構數組、鍊表、棧、隊列 散列表、二叉樹、堆 跳表、圖>5.常用算法 遞歸、排序、二分查找 搜索、哈希、貪心、分治 動態規劃、字符串匹配2.考考你在上一篇:數據結構與算法系列十(排序概述)中,我們列舉了常用的排序算法,以及分析了如何綜合衡量排序算法的優劣
  • JAVA並發編程:並發問題的根源及主要解決方法
    比如java中簡單的一條語句count += 1。映射到CPU指令有三條,讀取count變量指令,變量加1指令,變量寫回指令。雖然在高級語言(java)看來它就是一條指令,但實際上卻是三條CPU指令,並且這三條指令的原子性無法保證。也就是說,可能在執行到任意一條指令的時候被打斷,CPU被其他線程搶佔了。