Java自帶消息隊列Queue的使用教程詳細講解
阻塞隊列和非阻塞隊列
非阻塞隊列
- ConcurrentLinkedQueue
單向鏈表結(jié)構(gòu)的無界并發(fā)隊列, 非阻塞隊列,由CAS實現(xiàn)線程安全,內(nèi)部基于節(jié)點實現(xiàn)
- ConcurrentLinkedDeque
雙向鏈表結(jié)構(gòu)的無界并發(fā)隊列, 非阻塞隊列,由CAS實現(xiàn)線程安全
- PriorityQueue
內(nèi)部基于數(shù)組實現(xiàn),線程不安全的隊列
阻塞隊列
- DelayQueue
一個支持延時獲取元素的無界阻塞隊列
- LinkedTransferQueue
一個由鏈表結(jié)構(gòu)組成的無界阻塞隊列。
- ArrayBlockingQueue
有界隊列,阻塞式,初始化時必須指定隊列大小,且不可改變;,底層由數(shù)組實現(xiàn);
- SynchronousQueue
最多只能存儲一個元素,每一個put操作必須等待一個take操作,否則不能繼續(xù)添加元素
- PriorityBlockingQueue
一個帶優(yōu)先級的隊列,而不是先進先出隊列。元素按優(yōu)先級順序被移除,而且它也是無界的,也就是沒有容量上限,雖然此隊列邏輯上是無界的,但是由于資源被耗盡,所以試圖執(zhí)行添加操作可能會導(dǎo)致 OutOfMemoryError 錯誤;

以ArrayBlockingQueue為例實現(xiàn)阻塞隊列,非阻塞隊列這里就不說了,方法都是差不多的。
拋出異常
適用場景極少。因為程序就是要穩(wěn)定的運行,盡量不要拋出異常。
private static final BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
//拋出異常
@Test
public void test(){
System.out.println(blockingQueue.add("a"));
System.out.println(blockingQueue.add("b"));
System.out.println(blockingQueue.add("c"));
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
// System.out.println(blockingQueue.remove()); //移除隊列當(dāng)中的元素,如果有則返回移除的元素,沒有則拋出異常:java.util.NoSuchElementException。
// System.out.println(blockingQueue.element()); //獲取隊列當(dāng)中的元素,如果有則返回,沒有則拋出異常:java.util.NoSuchElementException。
// System.out.println(blockingQueue.add("d")); //當(dāng)隊列已滿時,往隊列里添加元素,則會拋出異常:Queue full。
}特殊值
新消息添加進隊列時,如果當(dāng)前隊列已滿,則會被直接拋棄,導(dǎo)致消息丟失。
private static final BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
//特殊值
@Test
public void test2(){
System.out.println(blockingQueue.offer("a"));
System.out.println(blockingQueue.offer("b"));
System.out.println(blockingQueue.offer("c"));
System.out.println(blockingQueue.offer("d")); //往隊列里面添加元素,超出隊列長度則返回false。
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll()); //移除隊列里面的元素,如果有元素,則返回元素,沒有則返回null。
}阻塞
消息處理過快會一直阻塞,這個沒什么問題。但是如果消息處理過慢,則會消息大量積壓,導(dǎo)致cpu占用過高程序崩潰。
private static final BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
//阻塞
@Test
public void test3() throws InterruptedException {
blockingQueue.put("a");
blockingQueue.put("b");
blockingQueue.put("c");
// blockingQueue.put("d"); //如果隊列已經(jīng)滿了,則一直阻塞,直到隊列有位置。
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
// System.out.println(blockingQueue.take()); //如果隊列沒有元素,則一直阻塞,直到隊列有元素。
}超時
如果隊列已滿,則在指定時間之后再次嘗試往隊列里面設(shè)置元素,設(shè)置成功返回true,失敗返回false。這相比較上面的來說會好很多,相當(dāng)于有2次機會往隊列里面設(shè)置元素。移除元素也是同理。
private static final BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
//超時
@Test
public void test4() throws InterruptedException {
System.out.println(blockingQueue.offer("a"));
System.out.println(blockingQueue.offer("b"));
System.out.println(blockingQueue.offer("c"));
System.out.println(blockingQueue.offer("d",3, TimeUnit.SECONDS)); //往隊列里面添加元素,如果隊列已滿,則等待指定時間再次往隊列里面設(shè)置元素,設(shè)置成功返回true,失敗返回false。
System.out.println(blockingQueue.poll(3,TimeUnit.SECONDS)); //移除隊列里面的元素,如果隊列里面有元素,則返回元素,沒有則等待指定時間再次移除隊列里面的元素,如果有元素則返回元素,沒有則返回null
}總結(jié)
使用隊列時應(yīng)該考慮隊列的作用是一邊積壓消息,一邊處理消息,而且要保證隊列不會造成消息大量積壓。所以我們可以讓隊列不停的進行設(shè)置元素,然后寫個定時任務(wù),按照指定的時間,不停的消費隊列里面的全部元素。這個指定時間要根據(jù)業(yè)務(wù)量去設(shè)置,如果業(yè)務(wù)量太少,時間間隔可以設(shè)置的長一點。業(yè)務(wù)量大設(shè)置的短一點,如:1s執(zhí)行一次,一次全部取完隊列里的元素。這種情況就不建議使用固定長度的消息隊列,而應(yīng)該使用自動擴容的消息隊列,因為你無法直到消息隊列的具體長度是多少。
到此這篇關(guān)于Java自帶消息隊列Queue的使用教程詳細講解的文章就介紹到這了,更多相關(guān)Java自帶消息隊列Queue內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring中@Configuration和@Component注解的區(qū)別及原理
這篇文章主要介紹了Spring中@Configuration和@Component注解的區(qū)別及原理,從功能上來講,這些注解所負責(zé)的功能的確不相同,但是從本質(zhì)上來講,Spring內(nèi)部都將其作為配置注解進行處理,需要的朋友可以參考下2023-11-11
SpringDataJpa:JpaRepository增刪改查操作
這篇文章主要介紹了SpringDataJpa:JpaRepository增刪改查操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08
JAVA實現(xiàn)經(jīng)典游戲坦克大戰(zhàn)的示例代碼
小時候大家都玩過坦克大戰(zhàn)吧,熟悉的旋律和豐富的關(guān)卡陪伴了我們一整個寒暑假。本文將通過Java+Swing實現(xiàn)這一經(jīng)典游戲,感興趣的可以學(xué)習(xí)一下2022-01-01
Spring Boot整合logback一個簡單的日志集成架構(gòu)
今天小編就為大家分享一篇關(guān)于Spring Boot整合logback一個簡單的日志集成架構(gòu),小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-01-01
Android 應(yīng)用按返回鍵退向后臺運行實例代碼
這篇文章主要介紹了Android 應(yīng)用按返回鍵退向后臺運行實例代碼的相關(guān)資料,需要的朋友可以參考下2017-04-04

