Java BlockingQueue接口java.util.concurrent.BlockingQueue
表示一個能夠存取元素,而且線程安全的隊列。換句話說,當多線程同時從 JavaBlockingQueue
中插入元素、獲取元素的時候,不會致使任何併發問題(元素被插入屢次、處理屢次等問題)。vue
從java BlockingQueue
能夠引伸出一個概念:阻塞隊列,是指隊列自己能夠阻塞線程向隊列裏面插入元素,或者阻塞線程從隊列裏面獲取元素。好比:當一個線程嘗試去從一個空隊列裏面獲取元素的時候,這個線程將被阻塞直到隊列內元素數量再也不爲空。固然,線程是否會被阻塞取決於你調用什麼方法從BlockingQueue
獲取元素,有的方法會阻塞線程,有的方法會拋出異常等等,下文咱們會詳細介紹。java
本文不會去介紹如何本身實現BlockingQueue
接口,JUC已經爲咱們作好了相關的一些接口實現類。BlockingQueue
是一個java接口,當咱們須要使用阻塞隊列的時候,可使用它的實現類。java.util.concurrent
包裏面有以下的一些實現類實現了BlockingQueue
接口。redis
在本文以及後續的文章中,會依次爲你們介紹這些實現類的做用及使用場景,期待您的關注。spring
BlockingQueue
一般被應用在一個線程生產對象放入隊列,與此同時另外一個線程消費隊列內的對象的場景下。下面的這張圖說明了使用場景:後端
生產者線程不斷的生產新的對象,並將他們插入到BlockingQueue
,直到隊列中object的數量達到隊列存儲容量的上限。也就是說當隊列中對象達到容量上限的時候,生產者線程將被阻塞,不能再向隊列中插入新的對象。生產者線程將保持阻塞等待狀態,直到消費者線程從隊列中拿走Object,讓隊列有空餘位置放入新的對象。安全
消費者線程不斷的從BlockingQueue
取出對象並將其進行處理。若是消費者線程嘗試從一個空隊列中獲取一個對象,消費者線程將被阻塞處於等待狀態,直到生產者向隊列中放入一個新的對象。springboot
因此BlockingQueue常常被用於生產消費的緩衝隊列,若是你不想用分佈式的或者中間件消息隊列(redis、kafka)等(由於對於一個小功能會增長比較大的獨立中間件運維成本),BlockingQueue能夠能是一個備選的選項。數據結構
JavaBlockingQueue
提供了四組不一樣的方法用於向隊列中插入、移除、檢查隊列中包含某一元素對象。每一組方法在被調用以後的響應行爲上有所不一樣,以下:多線程
拋出異常 | 返回特定值 | 阻塞後一直等待 | 阻塞後等待超時 | |
---|---|---|---|---|
插入對象 | add(o) | offer(o) | put(o) | offer(o, timeout, timeunit) |
移除對象 | remove(o) | poll() | take() | poll(timeout, timeunit) |
檢查對象存在 | element() | peek() |
上面的方法的四種行爲分別的含義是併發
另外,BlockingQueue
隊列不容許向其內部插入null,若是你向隊列中插入null,將會引起NullPointerException
異常。
通常的隊列都是從隊首放入對象,從隊尾獲取對象,BlockingQueue
不只支持從隊首隊尾操做數據對象,還支持從隊列中其餘任何位置操做數據。好比:你已經向隊列中放入一個對象並等待處理,可是出於某些特殊緣由但願將這個對象從隊列中刪除掉。你能夠調用remove(o)
方法來刪除隊列中的一個特定的o對象。固然咱們的程序不能常常性的這樣作,由於隊列這種數據結構常常從中間位置操做數據的效率是極低的,因此除非必要不建議這樣作。
BlockingQueueadd()
方法能夠將o對象以參數的形式插入到隊列裏面,若是隊列裏面有剩餘空間,將被當即插入;若是隊列裏面沒有剩餘空間,add()
方法將跑出 IllegalStateException.
BlockingQueueoffer()
方法能夠將o對象以參數的形式插入到隊列裏面,若是隊列裏面有剩餘空間,將被當即插入;若是隊列裏面沒有剩餘空間,offer()
方法將返回特定的值false
.
BlockingQueueoffer()
方法有另一個版本的實現,存在超時時間的設置參數。這個版本的offer()
方法將o對象以參數的形式插入到隊列裏面,若是隊列裏面有剩餘空間,將被當即插入;若是隊列裏面沒有剩餘空間,調用offer方法的線程在超時時間內將被阻塞處於等到狀態,當阻塞時間大於超時時間以後,隊列內若是仍然沒有剩餘空間放入新對象,offer()
方法將返回false
.
BlockingQueueput()
方法能夠將o對象以參數的形式插入到隊列裏面,若是隊列裏面有剩餘空間,將被當即插入;若是隊列裏面沒有剩餘空間,調用put的方法的線程將被阻塞,直到BlockingQueue裏面騰出新的空間能夠放入對象爲止。
BlockingQueuetake()
方法取出並移除隊列中的第一個元素(對象),若是BlockingQueue隊列中不包含任何的元素,調用take()
方法的線程將被阻塞,直到有新的元素對象插入到隊列中爲止。
BlockingQueuepoll()
方法取出並移除隊列中的第一個元素(對象),若是BlockingQueue隊列中不包含任何的元素,poll()
方法將返回null
.
BlockingQueuepoll(long timeMillis, TimeUnit timeUnit)
方法一樣存在一個超時時間限制的版本,正常狀況下該方法取出並移除隊列中的第一個元素(對象)。若是BlockingQueue隊列中不包含任何的元素,在超時時間範圍內,若是仍然沒有新的對象放入隊列,這個版本的poll()
方法將被阻塞處於等待狀態;當阻塞時間大於超時時間以後,poll(long timeMillis, TimeUnit timeUnit)
返回null
BlockingQueueremove(Object o)
方法能夠從隊列中刪除一個以參數形式給定的元素對象,remove()
方法使用o.equals(element)
將傳入參數o與隊列中的對象進行一一比對,從而斷定要刪除的對象是否在隊列中存在,若是存在就從隊列中刪除並返回true,不然返回false。
須要注意的是:若是隊列中有多個與傳入參數equals相等的對象,只刪除其中一個,不會將隊列中全部匹配的對象都刪除。
BlockingQueuepeek()
方法將取出隊列中的第一個元素對象,可是並不會將其從隊列中刪除。若是隊列中目前沒有任何的元素,也就是空隊列,peek()
方法將返回null
.
BlockingQueueelement()
方法將取出隊列中的第一個元素對象,可是並不會將其從隊列中刪除。若是隊列中目前沒有任何的元素,也就是空隊列,element()
方法將拋出 NoSuchElementException.
BlockingQueuecontains(Object o)
方法用來判斷當前隊列中是否存在某個對象,該對象與傳入參數o相等(Objects.equals(o, element)
被用來斷定對象的相等性)。遍歷隊列中的全部元素,一旦在隊列中發現匹配的元素對象,該方法將返回true;若是沒有任何的元素匹配相等,該方法返回false。
drainTo(Collection dest)
方法一次性的將隊列中的全部元素取出到集合類Collection dest對象中保存。
drainTo(Collection dest)
方法一次性的從隊列中取出maxElements個元素到集合類Collection dest對象中保存。
BlockingQueuesize()
方法返回隊列中目前共有多少個元素
BlockingQueueremainingCapacity()
方法將返回隊列目前還剩多少個可用空間用於放入新的對象。剩餘空間容量=隊列的總容量-已經被佔用的空間數量
本文轉載註明出處(必須帶鏈接,不能只轉文字):字母哥博客 - zimug.com
以爲對您有幫助的話,幫我點贊、分享!您的支持是我不竭的創做動力! 。另外,筆者最近一段時間輸出了以下的精品內容,期待您的關注。