Java阻塞隊列

1、阻塞隊列:用於保存等待執行的任務。在阻塞隊列中,線程阻塞的兩種狀況:數組

  1.當隊列中沒有數據的狀況下,消費者端的全部線程都會被自動阻塞(掛起),直到有數據放入隊列。緩存

  

  2.當隊列中填滿數據的狀況下, 生產者端的全部線程都會被自動阻塞,知道隊列中有空位置,線程被自動喚醒。多線程

  

2、阻塞隊列的主要方法併發

  拋出異常:拋出一個異常;函數

  特殊值:返回一個特殊值(null或false,視狀況而定)高併發

  阻塞:在成功操做以前,一直阻塞線程性能

  超時:放棄前只在最大的時間內阻塞this

插入操做spa

  1)public abstract boolean add(E paramE):將指定元素插入此隊列中(若是當即可行且不會違反容量限制),成功是返回true,若是當前沒有可用空間,則拋出異常。若是鈣元素是null,則會拋出NullPointerException異常。線程

  2)public abstract boolean offer(E paramE):將指定元素插入此隊列中(若是當即可行且不會違反容量限制),成功時返回true,若是當前沒有可用的空間,則返回false。

  3)public abstract void put(E paramE)throws InterruptedExcaption:將指定元素插入隊列中,將等待可用的空間(若是有必要)。

 1 public void put(E paramE) throws InterruptedException {  2  checkNotNull(paramE);  3      ReentrantLock  localReentrantLock = this.lock;  4  localReentrantLock.lockInterruptibly();  5   try {  6          while (this.count == this.items.length)  7          this.notFull.await();//若是隊列滿了,則線程阻塞等待
 8  enqueue(paramE);  9  localReentrantLock.unlock(); 10      } finally { 11  localReentrantLock.unlock(); 12  } 13  }

  4)offer(E o,long timeout, TimeUnit unit):能夠設定等待的時間,若是指定的時間內,還不能往隊列中加入BlockingQueue,則返回失敗。

獲取數據操做

  1)poll(time):取走BlockingQueue裏排在首位的對象,若不能當即取出,則能夠等time參數規定的時間,取不到時返回null;

  2)poll(long timeout,TimeUnit unit):從BlockingQueue取出一個隊首的對象,若是在指定的時間內,隊列一旦有數據可取,則當即返回隊列中的數據。不然直到時間超時尚未數據可取,返回失敗;

  3)take():取走BlockingQueue裏排在首位的對象,若BlockingQueue爲空,阻斷進入等待狀態直到BlockingQueue有新的數據被加入;

  4)drainTo():一次性從BlockingQueue獲取全部可用的數據對象(還能夠指定獲取數據的個數),經過該方法,能夠提高獲取數據效率,不須要屢次分批加鎖或釋放鎖。

3、Java中的阻塞隊列

  1. ArrayBlockingQueue:由數組結構實現的有界阻塞隊列。此隊列按照先進先出(FIFO)的原則對元素進行排序。默認狀況下不保證訪問者公平的訪問隊列,所謂的公平訪問隊列是指阻塞的全部生產者線程或消費者線程,當隊列可用時,能夠按照阻塞的前後順序訪問隊列,即先阻塞的生產者線程,能夠先往隊列裏插入元素,先阻塞的消費者線程,能夠先從隊列裏獲取元素。一般狀況下爲了保證公平性會下降吞吐量。咱們可使用如下代碼建立一個公平的阻塞隊列:

    ArrayBlockingQueue fairQueue = new ArrayBlockingQueue(1000,ture);

  2. LinkedBlockingQueue:由鏈表結構組成的有界阻塞隊列。同ArrayBlockingQueue相似,此隊列按照先進先出(FIFO)的原則對元素進行排序。而LinkedBlockingQueue之因此可以高效地處理併發數據,還由於其對於生產者端和消費者端分別採用了獨立的鎖來控制數據同步,在高併發的狀況下生產者和消費者能夠並行地操做隊列中的數據,以此來提升整個隊列的併發性能。吞吐量一般要高於ArrayBlockingQueue。

    LinkedBlockingQueue會默認一個相似無限大小的容量(Integer.MAX_VALUE)。

  3. PriorityBlockingQueue:支持優先級排序的無界阻塞隊列。默認狀況下元素採起升序排列。能夠自定義實現compareTo() 方法來指定元素進行排序規則,或初始化PriorityBlockingQueue時,制定構造函數Comparator來對元素進行排序。須要注意的是不能保證同優先級元素的順序。

  4. DelayQueue:使用優先級隊列實現的支持延時獲取元素的無界阻塞隊列。隊列使用PriorityQueue來實現。隊列中的元素必須實現Delayed接口,在建立元素是能夠指定多久才能從隊列中獲取當前元素。只有在延遲期滿時才能從隊列中提取元素。咱們能夠將DelayQueue運用在如下場景中:

    1)緩存系統的設計:能夠用DelayQueue保存緩存元素的有效期,使用一個線程循環查詢DelayQueue,一旦能從DelayQueue中獲取元素時,表示緩存有效期到了。

    2)定時任務調度:使用DelayQueue保存當天將會執行的任務和執行時間,一旦從DelayQueue中獲取到任務就開始執行,從好比TimerQueue就是使用DelayQueue實現的。

  5. SynchronousQueue:是一個不存儲元素的阻塞隊列。每一個插入操做必須等到另外一個線程調用移除操做,不然插入操做一直處於阻塞狀態。SynchronousQueue負責把生產者線程處理的數據直接傳遞給消費者線程。隊列自己並不存儲任何元素,很是適合於傳遞性場景,好比在一個線程中使用的數據,傳遞給另一個線程使用,SynchronousQueue的吞吐量高於LinkedBlockingQueue和ArrayBlockingQueue。

  6. LinkedTransferQueue:由鏈表結構組成的無界阻塞隊列。相對於其餘阻塞隊列,LinkedTransferQueue多了tryTransfer和transfer方法。

    1)transfer方法:若是當前有消費者正在等待接收元素(消費者使用take方法或帶時間限制的poll方法時),transfer方法能夠把生產者傳入的元素馬上transfer(傳輸)給消費者。若是沒有消費者在等待接收元素,transfer方法會將元素存放在隊列的tail節點,並等待該元素被消費者消費了才返回。

    2)tryTransfer方法:是用來試探下生產者傳入的元素是否能直接傳給消費者。若是沒有消費者等待接收元素,則返回false。tryTransfer方法與transfer方法的區別是tryTransfer方法不管消費者是否接收,方法當即返回,而transfer方法是必須等到消費者消費了才返回。對於帶有時間限制的tryTransfer(E o,long timeout,TimeUnit unit)方法,則是試圖把生產者傳入的元素直接傳給消費者,可是若是沒有消費者消費該元素則等待指定的時間再返回,若是超時還沒消費元素,則返回false,若是在超市時間內消費了元素,則返回true。

  7.LinkedBlockingDeque:由鏈表結構組成的雙向阻塞隊列。所謂雙向隊列指能夠從隊列的兩端插入和移除元素。雙端隊列由於多了一個操做隊列的入口,在多線程同時入隊時,也就減小了一半的競爭。相比其餘的阻塞隊列,LinkedBlockingDeque多了addFirst,addLast,offerFirst,offerLast,peekFirst,peekLast等方法,以First單詞結尾的方法,表示插入、獲取(peek)或移除雙端隊列第一個元素。以Last單詞結尾的方法,表示插入、獲取或移除雙端隊列的最後一個元素。另外插入方法add等同於addLast,移除方法remove等同於removeFirst。可是take方法卻等同於takeFirst,使用時仍是用帶有First和Last後綴的方法更清楚。在初始化LinkedBlockingQueue時能夠設置容量防止其過分膨脹。另外雙向阻塞隊列能夠運用在「工做竊取」模式中。

相關文章
相關標籤/搜索