日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java 队列已满_JAVA中常见的阻塞队列详解

發布時間:2023/12/14 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 队列已满_JAVA中常见的阻塞队列详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在之前的線程池的介紹中我們看到了很多阻塞隊列,這篇文章我們主要來說說阻塞隊列的事。

阻塞隊列也就是?BlockingQueue?,這個類是一個接

口,同時繼承了?Queue?接口,這兩個接口都是在JDK5?中加入的 。

BlockingQueue?阻塞隊列是線程安全的,在我們業務中是會經常頻繁使用到的,如典型的生產者消費的場景,生產者只需要向隊列中添加,而消費者負責從隊列中獲取。

如上圖展示,我們生產者線程不斷的put?元素到隊列,而消費者從中take?出元素處理,這樣實現了任務與執行任務類之間的解耦,任務都被放入到了阻塞隊列中,這樣生產者和消費者之間就不會直接相互訪問實現了隔離提高了安全性。

并發隊列

上面是?Java?中隊列Queue?類的類圖,我們可以看到它分為兩大類,阻塞隊列與非阻塞隊列

阻塞隊列的實現接口是?BlockingQueue?而非阻塞隊列的接口是?ConcurrentLinkedQueue?, 本文主要介紹阻塞隊列,非阻塞隊列不再過多闡述

BlockingQueue?主要有下面六個實現類,分別是?ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue、DelayQueue、PriorityBlockingQueue、LinkedTransferQueue?。這些阻塞隊列有著各自的特點和適用場景,后面詳細介紹。

非阻塞隊列的典型例子如?ConcurrentLinkedQueue?, 它不會阻塞線程,而是利用了?CAS?來保證線程的安全。

其實還有一個隊列和?Queue?關系很緊密,那就是Deque,這其實是?double-ended-queue?的縮寫,意思是雙端隊列。它的特點是從頭部和尾部都能添加和刪除元素,而我們常見的普通隊列Queue?則是只能一端進一端出,即FIFO?。

阻塞隊列特點阻塞隊列的特點就在于阻塞,它可以阻塞線程,讓生產者消費者得以平衡,阻塞隊列中有兩個關鍵方法?Put?和?Take?方法

take方法take?方法的功能是獲取并移除隊列的頭結點,通常在隊列里有數據的時候是可以正常移除的??墒且坏﹫绦?take?方法的時候,隊列里無數據,則阻塞,直到隊列里有數據。一旦隊列里有數據了,就會立刻解除阻塞狀態,并且取到數據。過程如圖所示:

?put方法put?方法插入元素時,如果隊列沒有滿,那就和普通的插入一樣是正常的插入,但是如果隊列已滿,那么就無法繼續插入,則阻塞,直到隊列里有了空閑空間。如果后續隊列有了空閑空間,比如消費者消費了一個元素,那么此時隊列就會解除阻塞狀態,并把需要添加的數據添加到隊列中。過程如圖所示:

?是否有界(容量有多大)此外,阻塞隊列還有一個非常重要的屬性,那就是容量的大小,分為有界和***兩種。

***隊列意味著里面可以容納非常多的元素,例如?LinkedBlockingQueue?的上限是?Integer.MAX_VALUE,約為 2 的 31 次方,是非常大的一個數,可以近似認為是無限容量,因為我們幾乎無法把這個容量裝滿。

但是有的阻塞隊列是有界的,例如?ArrayBlockingQueue?如果容量滿了,也不會擴容,所以一旦滿了就無法再往里放數據了。

阻塞隊列常見方法首先我們從常用的方法出發,根據各自的特點我們可以大致分為三個大類,如下表所示:分類方法含義特點拋出異常add添加一個元素如果隊列已滿,添加則拋出??IllegalStateException?異常

remove刪除隊列頭節點當隊列為空后,刪除則拋出??NoSuchElementException?異常

element獲取隊列頭元素當隊列為空時,則拋出?NoSuchElementException?異常

返回無異常offer添加一個元素當隊列已滿,不會報異常,返回??false?,如果成功返回?true

poll獲取隊列頭節點,并且刪除它當隊列空時,返回??Null

peek單純獲取頭節點當隊列為空時反饋?NULL

阻塞put添加一個元素如果隊列已滿則阻塞

take返回并刪除頭元素如果隊列為空則阻塞如上面所示主要的八個方法,相對都比較簡單,下面我們通過實際代碼演示的方式來認識

拋異常類型[add、remove、element]

add向隊列中添加一個元素。如果隊列是有界隊列,當隊列已滿時再添加則拋出異常提示,如下:BlockingQueue?queue?=?new?ArrayBlockingQueue(2);

queue.add(1);

queue.add(2);

queue.add(3);

上述代碼中我們創建了一個阻塞隊列容量為2,當我們使用?add?向其中添加元素,當添加到第三個時則會拋出異常如下:

removeremove?方法是從隊列中刪除隊列的頭節點,同時會返回該元素。當隊列中為空時執行?remove?方法時則會拋出異常,代碼如下:private?static?void?groupRemove()?{

BlockingQueue?queue?=?new?ArrayBlockingQueue(2);

queue.add("i-code.online");

System.out.println(queue.remove());

System.out.println(queue.remove());

}

上述代碼中,我們可以看到,我們想隊列中添加了一個元素?i-code.online?, 之后通過?remove?方法進行刪除,當執行第二次remove?時隊列內已無元素,則拋出異常。如下:

elementelement?方法是獲取隊列的頭元素,但是并不是刪除該元素,這也是與?remove?的區別,當隊列中沒有元素后我們再執行?element?方法時則會拋出異常,代碼如下:private?static?void?groupElement()?{

BlockingQueue?queue?=?new?ArrayBlockingQueue(2);

queue.add("i-code.online");

System.out.println(queue.element());

System.out.println(queue.element());

}private?static?void?groupElement2()?{

BlockingQueue?queue?=?new?ArrayBlockingQueue(2);

System.out.println(queue.element());

}

上面兩個方法分別演示了在有元素和無元素的情況element?的使用。在第一個方法中并不會報錯,因為首元素一直存在的,第二個方法中因為空的,所以拋出異常,如下結果:

無異常類型[offer、poll、peek]

offeroffer?方法是向隊列中添加元素, 同時反饋成功與失敗,如果失敗則返回?false?,當隊列已滿時繼續添加則會失敗,代碼如下:private?static?void?groupOffer()?{

BlockingQueue?queue?=?new?ArrayBlockingQueue(2);

System.out.println(queue.offer("i-code.online"));

System.out.println(queue.offer("云棲簡碼"));

System.out.println(queue.offer("AnonyStar"));

}

如上述代碼所示,我們向一個容量為2的隊列中通過offer?添加元素,當添加第三個時,則會反饋?false?,如下結果:truetruefalse

pollpoll?方法對應上面?remove?方法,兩者的區別就在于是否會在無元素情況下拋出異常,poll?方法在無元素時不會拋出異常而是返回null?,如下代碼:private?static?void?groupPoll()?{

BlockingQueue?queue?=?new?ArrayBlockingQueue(2);

System.out.println(queue.offer("云棲簡碼"));?//添加元素System.out.println(queue.poll());?//取出頭元素并且刪除????????System.out.println(queue.poll());

}

上面代碼中我們創建一個容量為2的隊列,并添加一個元素,之后調用兩次poll方法來獲取并刪除頭節點,發現第二次調用時為null?,因為隊列中已經為空了,如下:true云棲簡碼null

peekpeek?方法與前面的?element?方法是對應的 ,獲取元素頭節點但不刪除,與其不同的在于peek?方法在空隊列下并不會拋出異常,而是返回?null,如下:private?static?void?groupPeek()?{

BlockingQueue?queue?=?new?ArrayBlockingQueue(2);

System.out.println(queue.offer(1));

System.out.println(queue.peek());

System.out.println(queue.peek());

}private?static?void?groupPeek2()?{

BlockingQueue?queue?=?new?ArrayBlockingQueue(2);

System.out.println(queue.peek());

}

如上述代碼所示,我么們分別展示了非空隊列與空隊列下peek?的使用,結果如下:

阻塞類型[put、take]

putput?方法是向隊列中添加一個元素,這個方法是阻塞的,也就是說當隊列已經滿的情況下,再put元素時則會阻塞,直到隊列中有空位.

taketake?方法是從隊列中獲取頭節點并且將其移除,這也是一個阻塞方法,當隊列中已經沒有元素時,take?方法則會進入阻塞狀態,直到隊列中有新的元素進入。

常見的阻塞隊列

ArrayBlockingQueueArrayBlockingQueue?是一個我們常用的典型的有界隊列,其內部的實現是基于數組來實現的,我們在創建時需要指定其長度,它的線程安全性由?ReentrantLock?來實現的。public?ArrayBlockingQueue(int?capacity)?{...}public?ArrayBlockingQueue(int?capacity,?boolean?fair)?{...}如上所示,ArrayBlockingQueue?提供的構造函數中,我們需要指定隊列的長度,同時我們也可以設置隊列是都是公平的,當我們設置了容量后就不能再修改了,符合數組的特性,此隊列按照先進先出(FIFO)的原則對元素進行排序。

和?ReentrantLock?一樣,如果?ArrayBlockingQueue?被設置為非公平的,那么就存在插隊的可能;如果設置為公平的,那么等待了最長時間的線程會被優先處理,其他線程不允許插隊,不過這樣的公平策略同時會帶來一定的性能損耗,因為非公平的吞吐量通常會高于公平的情況。

LinkedBlockingQueue從它的名字我們可以知道,它是一個由鏈表實現的隊列,這個隊列的長度是?Integer.MAX_VALUE?,這個值是非常大的,幾乎無法達到,對此我們可以認為這個隊列基本屬于一個***隊列(也又認為是有界隊列)。此隊列按照先進先出的順序進行排序。

SynchronousQueuesynchronousQueue?是一個不存儲任何元素的阻塞隊列,每一個put操作必須等待take操作,否則不能添加元素。同時它也支持公平鎖和非公平鎖。

synchronousQueue?的容量并不是1,而是0。因為它本身不會持有任何元素,它是直接傳遞的,synchronousQueue?會把元素從生產者直接傳遞給消費者,在這個過程中能夠是不需要存儲的

在我們之前介紹過的線程池?CachedThreadPool?就是利用了該隊列。Executors.newCachedThreadPool(),因為這個線程池它的最大線程數是Integer.MAX_VALUE,它是更具需求來創建線程,所有的線程都是臨時線程,使用完后空閑60秒則被回收,

PriorityBlockingQueuePriorityBlockingQueue?是一個支持優先級排序的***阻塞隊列,可以通過自定義實現?compareTo()?方法來指定元素的排序規則,或者通過構造器參數?Comparator?來指定排序規則。但是需要注意插入隊列的對象必須是可比較大小的,也就是?Comparable?的,否則會拋出?ClassCastException?異常。

它的?take?方法在隊列為空的時候會阻塞,但是正因為它是***隊列,而且會自動擴容,所以它的隊列永遠不會滿,所以它的?put?方法永遠不會阻塞,添加操作始終都會成功

DelayQueueDelayQueue?是一個實現PriorityBlockingQueue的延遲獲取的***隊列。具有“延遲”的功能。

DelayQueue?應用場景:1. 緩存系統的設計:可以用DelayQueue保存緩存元素的有效期,使用一個線程循環查詢DelayQueue,一旦能從DelayQueue中獲取元素時,表示緩存有效期到了。2. 定時任務調度。使用DelayQueue保存當天將會執行的任務和執行時間,一旦從DelayQueue中獲取到任務就開始執行,從比如TimerQueue就是使用DelayQueue實現的。

它是***隊列,放入的元素必須實現?Delayed?接口,而?Delayed?接口又繼承了?Comparable?接口,所以自然就擁有了比較和排序的能力,代碼如下:public?interface?Delayed?extends?Comparable?{long?getDelay(TimeUnit?unit);

}

可以看出?Delayed?接口繼承?Comparable,里面有一個需要實現的方法,就是 ?getDelay。這里的?getDelay?方法返回的是“還剩下多長的延遲時間才會被執行”,如果返回 0 或者負數則代表任務已過期。

元素會根據延遲時間的長短被放到隊列的不同位置,越靠近隊列頭代表越早過期。

有完整的Java初級,高級對應的學習路線和資料!專注于java開發。分享java基礎、原理性知識、JavaWeb實戰、spring全家桶、設計模式、分布式及面試資料、開源項目,助力開發者成長!歡迎關注微信公眾號:碼邦主

總結

以上是生活随笔為你收集整理的java 队列已满_JAVA中常见的阻塞队列详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲天堂中文 | 成年人网站在线免费观看 | 亚洲麻豆av | 欧美性生活一区 | 成人av在线看 | 国产欧美日韩精品一区二区三区 | 国内自拍区 | 91久久精品国产91性色tv | 日本中文字幕有码 | 五月天婷婷综合 | 欧美日韩视频无码一区二区三 | www国产精品内射熟女 | 九九久久国产精品 | 九九热视频免费 | 亚洲图片欧美日韩 | 亚洲精品中文字幕乱码三区91 | 激情伦成人综合小说 | 以女性视角写的高h爽文 | 性色一区二区三区 | 国产精品一区二区三区在线看 | 手机成人在线视频 | 青青草草 | 国内精品卡一卡二卡三 | 制服丝袜国产精品 | 日本成人精品 | 亚洲成人系列 | 少妇大叫太粗太大爽一区二区 | 成人黄色在线看 | 国产精品午夜福利视频234区 | 精品www久久久久久奶水 | 色亚洲视频 | 亚洲手机视频 | 富二代成人短视频 | 青草草在线| 天堂素人 | 一本av在线 | 中文字幕人成乱码熟女香港 | 国产a一区二区三区 | 琪琪射 | 欧美a在线观看 | 国产欧美日韩精品区一区二污污污 | 天天艹av| av激情四射 | 亚洲一区二区三区三州 | 亚洲黄色在线免费观看 | 色女人综合 | 毛片h| 波多野42部无码喷潮 | 国产成人精品一区二区三区 | 手机在线一区二区三区 | a天堂中文网| 女人的天堂网 | 4438全国成人免费 | 绿色地狱在线观看 | 国产伦精品一区二区三区免费迷 | 国产视频三级 | av直播在线观看 | 高清视频一区二区三区 | 色悠久久久 | 日韩精品字幕 | 中文字幕一区二区av | 黄色a网 | 91视频免费视频 | 亚洲国产精品成人无久久精品 | 国产精品亚洲色图 | 雨宫琴音一区二区三区 | 亚洲性图一区二区 | 国产在线免费av | 人妖黄色片 | 羞羞漫画在线播放 | 精品久久久久中文慕人妻 | 久久在线免费观看视频 | 成人在线视频免费观看 | 2022精品国偷自产免费观看 | 欧美草b| 午夜毛片电影 | 成人精品视频在线 | 99久久人妻精品免费二区 | 日韩欧美高清片 | 国产乱码精品一区二区三区精东 | 欧美成人aaa | 日韩一区二区免费在线观看 | 免费黄色小视频在线观看 | 免费观看视频一区二区 | 成人av动漫在线 | 亚洲天堂影院 | 成人在线不卡 | 亚洲第一av | 午夜精品福利一区二区 | 久久久久久久伊人 | 激情a| 成人中文字幕+乱码+中文字幕 | 激情综合亚洲 | 超碰97在线资源 | 日本熟妇色xxxxx日本免费看 | 男性裸体全身精光gay | 一区二区三区四区视频 | 在线视频观看你懂得 | 日鲁鲁 |