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()); //移除隊列當中的元素,如果有則返回移除的元素,沒有則拋出異常:java.util.NoSuchElementException。 // System.out.println(blockingQueue.element()); //獲取隊列當中的元素,如果有則返回,沒有則拋出異常:java.util.NoSuchElementException。 // System.out.println(blockingQueue.add("d")); //當隊列已滿時,往隊列里添加元素,則會拋出異常:Queue full。 }
特殊值
新消息添加進隊列時,如果當前隊列已滿,則會被直接拋棄,導(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。這相比較上面的來說會好很多,相當于有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)文章
使用SpringMVC響應(yīng)json格式返回的結(jié)果類型
這篇文章主要介紹了使用SpringMVC響應(yīng)json格式返回的結(jié)果類型,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07Intellij Idea中進行Mybatis逆向工程的實現(xiàn)
這篇文章主要介紹了Intellij Idea中進行Mybatis逆向工程的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-05-05SpringDataJPA實體類關(guān)系映射配置方式
這篇文章主要介紹了SpringDataJPA實體類關(guān)系映射配置方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12MyBatis-Plus使用ActiveRecord(AR)實現(xiàn)CRUD
本文將結(jié)合實例代碼,介紹MyBatis-Plus使用ActiveRecord(AR)實現(xiàn)CRUD,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧2021-07-07Springboot+Mybatis-plus不使用SQL語句進行多表添加操作及問題小結(jié)
這篇文章主要介紹了在Springboot+Mybatis-plus不使用SQL語句進行多表添加操作,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-04-04