Java 7中的TransferQueue 以及 SynchronousQueue

來源:互聯網
上載者:User

標籤:設定   線上   資訊   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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.