在Grizzly中,自帶了LinkedTransferQueue,和JDK 7自帶的LinkedTransferQueue有所不一樣,不一樣之處就是使用PaddedAtomicReference來提高併發性能,其實這是一種錯誤的編碼技巧,沒有意義! java
AtomicReference和LinkedTransferQueue的本質是樂觀鎖,樂觀鎖的在激烈競爭的時候性能都很糟糕,樂觀鎖應使用在非激烈競爭的場景,爲樂觀鎖優化激烈競爭下的性能,是錯誤的方向,由於若是須要激烈競爭,就應該使用悲觀鎖。 併發
如下是一個JDK中內置樂觀鎖悲觀鎖的對照表: oop
樂觀鎖 -----> 悲觀鎖 性能
AtomicInteger -----> Lock + volatile int 測試
AtomicLong -----> Lock + volatile long 優化
AtomicReference -----> Lock + volatile 編碼
LinkedTransferQueue -----> LinkedBlockingQueue spa
在激烈競爭中,LinkedTransferQueue的性能,遠遠低於LinkedBlockingQueue,使用PaddedAtomicReference優化也是同樣的。若是不激烈競爭,Padded-LinkedTransferQueue和LinkedTransferQueue相比也沒有什麼優點。 線程
因此Padded-AtomicReference也是一個僞命題,若是激勵競爭,爲何不使用Lock + volatile,若是非激烈競爭,使用PaddedAtomicReference對於AtomicReference又沒有優點。因此使用Padded-AtomicReference是一個錯誤的編碼技巧。 code
如下是測試代碼,50個線程爭用10個對象,這種激烈競爭下,使用LinkedTransferQueue比LinkedBlockingQueue大約慢10倍。
package com.alibaba.study; import java.util.concurrent.*; public class BlockingQueueTest { public static void main(String[] args) throws Exception { for (int i = 0; i < 3; ++i) { loop(); } } private static void loop() throws InterruptedException { final BlockingQueue<Object> queue = new LinkedBlockingQueue<Object>(); // final BlockingQueue<Object> queue = new LinkedTransferQueue<Object>(); for (int i = 0; i < 10; ++i) { queue.put(i); } final int THREAD_COUNT = 50; final CountDownLatch startLatch = new CountDownLatch(1); final CountDownLatch endLatch = new CountDownLatch(THREAD_COUNT); for (int i = 0; i < THREAD_COUNT; ++i) { Thread thread = new Thread() { public void run() { try { startLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } try { for (int i = 0; i < 1000 * 20; ++i) { Object item = queue.take(); queue.put(item); } } catch (Exception e) { e.printStackTrace(); } finally { endLatch.countDown(); } } }; thread.start(); } long startMillis = System.currentTimeMillis(); startLatch.countDown(); endLatch.await(); long millis = System.currentTimeMillis() - startMillis; System.out.println(queue.getClass().getName() + " : " + millis); } }