天天看點

java多線程之:SynchronousQueue隊列

SynchronousQueue是這樣一種阻塞隊列,其中每個 put 必須等待一個 take,反之亦然。同步隊列沒有任何内部容量,甚至連一個隊列的容量都沒有。 

     不能在同步隊列上進行 peek,因為僅在試圖要取得元素時,該元素才存在; 

     除非另一個線程試圖移除某個元素,否則也不能(使用任何方法)添加元素;也不能疊代隊列,因為其中沒有元素可用于疊代。隊列的頭是嘗試添加到隊列中的首個已排隊線程元素; 如果沒有已排隊線程,則不添加元素并且頭為 null。 

     對于其他 Collection 方法(例如 contains),SynchronousQueue 作為一個空集合。此隊列不允許 null 元素。

    它非常适合于傳遞性設計,在這種設計中,在一個線程中運作的對象要将某些資訊、 

事件或任務傳遞給在另一個線程中運作的對象,它就必須與該對象同步。 

    對于正在等待的生産者和使用者線程而言,此類支援可選的公平排序政策。預設情況下不保證這種排序。 

    但是,使用公平設定為 true 所構造的隊列可保證線程以 FIFO 的順序進行通路。 公平通常會降低吞吐量,但是可以減小可變性并避免得不到服務。 

    注意1:它一種阻塞隊列,其中每個 put 必須等待一個 take,反之亦然。同步隊列沒有任何内部容量,甚至連一個隊列的容量都沒有。 

    注意2:它是線程安全的,是阻塞的。 

    注意3:不允許使用 null 元素。 

    注意4:公平排序政策是指調用put的線程之間,或take的線程之間。公平排序政策可以查考ArrayBlockingQueue中的公平政策。 

    注意5:SynchronousQueue的以下方法: 

    * iterator() 永遠傳回空,因為裡面沒東西。 

    * peek() 永遠傳回null。 

    * put() 往queue放進去一個element以後就一直wait直到有其他thread進來把這個element取走。 

    * offer() 往queue裡放一個element後立即傳回,如果碰巧這個element被另一個thread取走了,offer方法傳回true,認為offer成功;否則傳回false。 

    * offer(2000, TimeUnit.SECONDS) 往queue裡放一個element但是等待指定的時間後才傳回,傳回的邏輯和offer()方法一樣。 

    * take() 取出并且remove掉queue裡的element(認為是在queue裡的。。。),取不到東西他會一直等。 

    * poll() 取出并且remove掉queue裡的element(認為是在queue裡的。。。),隻有到碰巧另外一個線程正在往queue裡offer資料或者put資料的時候,該方法才會取到東西。否則立即傳回null。 

    * poll(2000, TimeUnit.SECONDS) 等待指定的時間然後取出并且remove掉queue裡的element,其實就是再等其他的thread來往裡塞。 

    * isEmpty()永遠是true。 

    * remainingCapacity() 永遠是0。 

    * remove()和removeAll() 永遠是false。 

這是一個很有意思的阻塞隊列,其中每個插入操作必須等待另一個線程的移除操作,同樣任何一個移除操作都等待另一個線程的插入

操作。是以此隊列内部其

實沒有任何一個元素,或者說容量是0,嚴格說并不是一種容器。由于隊列沒有容量,是以不能調用peek操作,因為隻有移除元素時才有元素。

一個沒有容量的并發隊列有什麼用了?或者說存在的意義是什麼?

SynchronousQueue

的實作非常複雜,當然了如果真要去分析還是能夠得到一些經驗的,但是前面分析了過多的結構後,發現越來越陷于資料結構與算法裡面了。我的初衷是通過研究并

發實作的原理來更好的利用并發來最大限度的利用可用資源。是以在後面的章節中盡可能的少研究資料結構和算法,但是為了弄清楚裡面的原理,必不可免的會涉及

到一些這方面的知識,希望後面能夠适可而止。

再回到話題。SynchronousQueue

内部沒有容量,但是由于一個插入操作總是對應一個移除操作,反過來同樣需要滿足。那麼一個元素就不會再SynchronousQueue

裡面長時間停留,一旦有了插入線程和移除線程,元素很快就從插入線程移交給移除線程。也就是說這更像是一種信道(管道),資源從一個方向快速傳遞到另一方

向。

需要特别說明的是,盡管元素在SynchronousQueue 内部不會“停留”,但是并不意味之SynchronousQueue

内部沒有隊列。實際上SynchronousQueue

維護者線程隊列,也就是插入線程或者移除線程在不同時存在的時候就會有線程隊列。既然有隊列,同樣就有公平性和非公平性特性,公平性保證正在等待的插入線

程或者移除線程以FIFO的順序傳遞資源。

顯然這是一種快速傳遞元素的方式,也就是說在這種情況下元素總是以最快的方式從插入着(生産者)傳遞給移除着(消費者),這在多任務隊列中是最快處理任務的方式。線上程池的相關章節中還會更多的提到此特性。