Java 7中的TransferQueue
原文連結,譯文連結,作者:Alex Miller,譯者:Greenster,校對:樑海艦
TransferQueue繼承了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方法,可以確保佇列中被傳遞元素之前的所有元素都能被處理。
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)實現一個非阻塞的方法,這是避免序列化處理任務的關鍵。這篇論文還羅列了很多的細節和資料,如果你感興趣,非常值得一讀。