Java7中加入了JSR 166y規範對集合類和并發類庫的改進。其中的一項是增加了接口TransferQueue和其實作類LinkedTransferQueue。
TransferQueue繼承了BlockingQueue并擴充了一些新方法。
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操作實作一個非阻塞的方法,這是避免序列化處理任務的關鍵