標籤:設定 線上 資訊 images art 有趣 das tor java7
Java7中加入了JSR 166y規範對集合類和並發類庫的改進。其中的一項是增加了介面TransferQueue和其實作類別LinkedTransferQueue。
TransferQueue繼承了BlockingQueue(BlockingQueue又繼承了Queue)並擴充了一些新方法。BlockingQueue(和Queue)是Java 5中加入的介面,它是指這樣的一個隊列:當生產者向隊列添加元素但隊列已滿時,生產者會被阻塞;當消費者從隊列移除元素但隊列為空白時,消費者會被阻塞。
TransferQueue則更進一步,生產者會一直阻塞直到所添加到隊列的元素被某一個消費者所消費(不僅僅是添加到隊列裡就完事)。新添加的transfer方法用來實現這種約束。顧名思義,阻塞就是發生在元素從一個線程transfer到另一個線程的過程中,它有效地實現了元素線上程之間的傳遞(以建立Java記憶體模型中的happens-before關係的方式)。
TransferQueue還包括了其他的一些方法:兩個tryTransfer方法,一個是非阻塞的,另一個帶有timeout參數設定逾時時間的。還有兩個輔助方法hasWaitingConsumer()和getWaitingConsumerCount()。
當我第一次看到TransferQueue時,首先想到了已有的實作類別SynchronousQueue。SynchronousQueue的隊列長度為0,最初我認為這好像沒多大用處,但後來我發現它是整個Java Collection Framework中最有用的隊列實作類別之一,特別是對於兩個線程之間傳遞元素這種用例。
TransferQueue相比SynchronousQueue用處更廣、更好用,因為你可以決定是使用BlockingQueue的方法(譯者註:例如put方法)還是確保一次傳遞完成(譯者註:即transfer方法)。在隊列中已有元素的情況下,調用transfer方法,可以確保隊列中被傳遞元素之前的所有元素都能被處理。Doug Lea說從功能角度來講,LinkedTransferQueue實際上是ConcurrentLinkedQueue、SynchronousQueue(公平模式)和LinkedBlockingQueue的超集。而且LinkedTransferQueue更好用,因為它不僅僅綜合了這幾個類的功能,同時也提供了更高效的實現。
Joe Bowbeer提供了一篇William Scherer, Doug Lea, and Michael Scott的論文,在這篇論文中展示了LinkedTransferQueue的演算法,效能測試的結果表明它優於Java 5的那些類(譯者註:ConcurrentLinkedQueue、SynchronousQueue和LinkedBlockingQueue)。LinkedTransferQueue的效能分別是SynchronousQueue的3倍(非公平模式)和14倍(公平模式)。因為像ThreadPoolExecutor這樣的類在任務傳遞時都是使用SynchronousQueue,所以使用LinkedTransferQueue來代替SynchronousQueue也會使得ThreadPoolExecutor得到相應的效能提升。考慮到executor在並發編程中的重要性,你就會理解添加這個實作類別的重要性了。
Java 5中的SynchronousQueue使用兩個隊列(一個用於正在等待的生產者、另一個用於正在等待的消費者)和一個用來保護兩個隊列的鎖。而LinkedTransferQueue使用CAS操作(譯者註:參考wiki)實現一個非阻塞的方法,這是避免序列化處理任務的關鍵。這篇論文還羅列了很多的細節和資料,如果你感興趣,非常值得一讀。
SynchronousQueue
SynchronousQueue是這樣 一種阻塞隊列,其中每個 put 必須等待一個 take,反之亦然。同步隊列沒有任何內部容量,甚至連一個隊列的容量都沒有。
不能在同步隊列上進行 peek,因為僅在試圖要取得元素時,該元素才存在;
除非另一個線程試圖移除某個元素,否則也不能(使用任何方法)添加元素;
也不能迭代隊列,因為其中沒有元素可用於迭代。隊列的頭是嘗試添加到隊列中的首個已排隊線程元素; 如果沒有已排隊線程,則不添加元素並且頭為 null。
對於其他 Collection 方法(例如 contains),SynchronousQueue 作為一個空集合。此隊列不允許 null 元素。
同步隊列類似於 CSP 和 Ada 中使用的 rendezvous 通道。
它非常適合於傳遞性設計,在這種設計中,在一個線程中啟動並執行對象要將某些資訊、
事件或任務傳遞給在另一個線程中啟動並執行對象,它就必須與該對象同步。
對於正在等待的生產者和使用者線程而言,此類支援可選的公平排序策略。預設情況下不保證這種排序。
但是,使用公平設定為 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。
轉自:http://blog.csdn.net/hudashi/article/details/7076814
http://ifeve.com/java-transfer-queue/
http://www.cnblogs.com/wangzhongqiu/p/6441703.html
Java 7中的TransferQueue 以及 SynchronousQueue