并发编程-23J.U.C组件拓展之阻塞队列BlockingQueue 和 线程池
文章目錄
- 概述
- 阻塞隊列的常用場景
- 阻塞隊列的4種處理方式
- JDK 7提供的7個阻塞隊列
- ArrayBlockingQueue
- LinkedBlockingQueue
- PriorityBlockingQueue
- DelayQueue
- SynchronousQueue
- LinkedTransferQueue
- LinkedBlockingDeque
- 線程池
概述
阻塞隊列(BlockingQueue)是一個支持兩個附加操作的隊列。這兩個附加的操作支持阻塞的插入和移除方法.
-
支持阻塞的插入方法:意思是當隊列滿時,隊列會阻塞插入元素的線程,直到隊列不滿
-
支持阻塞的移除方法:意思是在隊列為空時,獲取元素的線程會等待隊列變?yōu)榉强?/font>
阻塞隊列的常用場景
阻塞隊列常用于生產(chǎn)者和消費者的場景,生產(chǎn)者是向隊列里添加元素的線程,消費者是從隊列里取元素的線程。阻塞隊列就是生產(chǎn)者用來存放元素、消費者用來獲取元素的容器。
阻塞隊列的4種處理方式
- 拋出異常
當隊列滿時,如果再往隊列里插入元素,會拋出IllegalStateException(“Queuefull”)異常。
當隊列空時,從隊列里獲取元素會拋出NoSuchElementException異常。
- 返回特殊值
當往隊列插入元素時,會返回元素是否插入成功,成功返回true。如果是移除方法,則是從隊列里取出一個元素,如果沒有則返回null。
- 一直阻塞
當阻塞隊列滿時,如果生產(chǎn)者線程往隊列里put元素,隊列會一直阻塞生產(chǎn)者線程,直到隊列可用或者響應中斷退出。
當隊列空時,如果消費者線程從隊列里take元素,隊列會阻塞住消費者線程,直到隊列不為空。
- 超時退出
當阻塞隊列滿時,如果生產(chǎn)者線程往隊列里插入元素,隊列會阻塞生產(chǎn)者線程一段時間,如果超過了指定的時間,生產(chǎn)者線程就會退出。
如果是無界阻塞隊列,隊列不可能會出現(xiàn)滿的情況,所以使用put或offer方法永遠不會被阻塞,而且使用offer方法時,該方法永遠返回true。
JDK 7提供的7個阻塞隊列
ArrayBlockingQueue
一個由數(shù)組結(jié)構(gòu)組成的有界阻塞隊列.
ArrayBlockingQueue是一個用數(shù)組實現(xiàn)的有界阻塞隊列。此隊列按照先進先出(FIFO)的原則對元素進行排序。
默認情況下不保證線程公平的訪問隊列.
所謂公平訪問隊列是指阻塞的線程,可以按照阻塞的先后順序訪問隊列,即先阻塞線程先訪問隊列。
非公平性是對先等待的線程是非公平的,當隊列可用時,阻塞的線程都可以爭奪訪問隊列的資格,有可能先阻塞的線程最后才訪問隊列。
為了保證公平性,通常會降低吞吐量。我們可以使用以下代碼創(chuàng)建一個公平的阻塞隊列。
ArrayBlockingQueue fairQueue = new ArrayBlockingQueue(1000,true);LinkedBlockingQueue
一個由鏈表結(jié)構(gòu)組成的有界阻塞隊列
LinkedBlockingQueue是一個用鏈表實現(xiàn)的有界阻塞隊列。此隊列的默認和最大長度為Integer.MAX_VALUE。此隊列按照先進先出的原則對元素進行排序。
PriorityBlockingQueue
一個支持優(yōu)先級排序的無界阻塞隊列
默認情況下元素采取自然順序升序排列。也可以自定義類實現(xiàn)compareTo()方法來指定元素排序規(guī)則,或者初始化PriorityBlockingQueue時,指定構(gòu)造參數(shù)Comparator來對元素進行排序。需要注意的是不能保證同優(yōu)先級元素的順序。
DelayQueue
一個使用優(yōu)先級隊列實現(xiàn)的無界阻塞隊列。
DelayQueue是一個支持延時獲取元素的無界阻塞隊列。隊列使用PriorityQueue來實現(xiàn)。隊列中的元素必須實現(xiàn)Delayed接口,在創(chuàng)建元素時可以指定多久才能從隊列中獲取當前元素。只有在延遲期滿時才能從隊列中提取元素。
SynchronousQueue
一個不存儲元素的阻塞隊列
SynchronousQueue是一個不存儲元素的阻塞隊列。每一個put操作必須等待一個take操作,否則不能繼續(xù)添加元素。
它支持公平訪問隊列。默認情況下線程采用非公平性策略訪問隊列。使用以下構(gòu)造方法可以創(chuàng)建公平性訪問的SynchronousQueue,如果設(shè)置為true,則等待的線程會采用先進先出的順序訪問隊列
public SynchronousQueue(boolean fair) {transferer = fair new TransferQueue() : new TransferStack(); }SynchronousQueue可以看成是一個傳球手,負責把生產(chǎn)者線程處理的數(shù)據(jù)直接傳遞給消費者線程。隊列本身并不存儲任何元素,非常適合傳遞性場景。
SynchronousQueue的吞吐量高于LinkedBlockingQueue和ArrayBlockingQueue。
LinkedTransferQueue
一個由鏈表結(jié)構(gòu)組成的無界阻塞隊列
LinkedTransferQueue是一個由鏈表結(jié)構(gòu)組成的無界阻塞TransferQueue隊列。相對于其他阻塞隊列,LinkedTransferQueue多了tryTransfer和transfer方法。
LinkedBlockingDeque
一個由鏈表結(jié)構(gòu)組成的雙向阻塞隊列
所謂雙向隊列指的是可以從隊列的兩端插入和移出元素。雙向隊列因為多了一個操作隊列的入口,在多線程同時入隊時,也就減少了一半的競爭。相比其他的阻塞隊列,LinkedBlockingDeque多了addFirst、addLast、offerFirst、offerLast、peekFirst和peekLast等方法,以First單詞結(jié)尾的方法,表示插入、獲取(peek)或移除雙端隊列的第一個元素。以Last單詞結(jié)尾的方法,表示插入、獲取或移除雙端隊列的最后一個元素。
線程池
很久以前總結(jié)過了,這里就不贅述了,見Java-Java中的線程池原理分析及使用
總結(jié)
以上是生活随笔為你收集整理的并发编程-23J.U.C组件拓展之阻塞队列BlockingQueue 和 线程池的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 并发编程-22J.U.C组件拓展之For
- 下一篇: 并发编程-24 高并发处理手段之扩容思路