Java中併發無外乎多線程加鎖等方式,平時用的比較多的就是util.concurrency下的一些工具。除此之外業界比較推崇的就是erlang、scala中較爲流行的actor模型,該模型是著名的無鎖模型,actor(可以簡單認爲是輕量線程)之間通過發送消息進行通信,由事件驅動,全程無鎖。
最近看論壇發現了另外一個併發模型-disruptor。它比較特殊,其核心是ringbuffer,閒來無事做了個簡單測試。用它來模擬典型的生產者-消費者問題,本例中一個消費者-一個生產者,並將disruptor和jdk提供的ArrayBlockingQueue做了對比,發現在本人的筆記本上前者比後者快將近10倍!
閒話少敘,直接貼代碼,如有意見或問題歡迎拍磚。
public class BqTest { static boolean ft = true; static boolean z = true; /** * <b>Title:</b> main</br> * <b>Description:</b> * @param args void * @throws: * @author: shenbaise */ public static void main(String[] args) { BqTest bt = new BqTest(); bt.test(); } public void test(){ long cost = System.currentTimeMillis(); final BlockingQueue<Long> bq = new ArrayBlockingQueue<Long>(4096); Runnable p = new Runnable() { public void run() { for(int i= 0;i<100000000;i++){ try { bq.put((long) i); } catch (InterruptedException e) { e.printStackTrace(); } } ft = false; } }; Runnable c = new Runnable() { public void run() { while(ft || !bq.isEmpty()){ try { bq.take(); } catch (InterruptedException e) { e.printStackTrace(); } } z = false; } }; new Thread(c).start(); new Thread(p).start(); while(z){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("cost:"+(System.currentTimeMillis() - cost)); } }
disruptor的測試稍微麻煩點。
public final class ValueEvent {
private long value;
public long getValue() {
return value;
}
public void setValue(final long value) {
this.value = value;
}
public final static EventFactory<ValueEvent> EVENT_FACTORY = new EventFactory<ValueEvent>() {
public ValueEvent newInstance() {
return new ValueEvent();
}
};
}
public class MyEventHandler implements EventHandler<ValueEvent>{
public long count = 0;
public void onEvent(ValueEvent arg0, long arg1, boolean arg2)
throws Exception {
arg0.getValue();
// 爲了公平這裏什麼都不做
}
}
/** * @author shenbaise */ public class RbTest { private static final int BUFFER_SIZE = 4096; public static void main(String[] args) { RbTest test = new RbTest(); test.test(); } public void test() { long cost = System.currentTimeMillis(); RingBuffer<ValueEvent> ringBuffer = createSingleProducer(ValueEvent.EVENT_FACTORY, BUFFER_SIZE, new YieldingWaitStrategy()); SequenceBarrier sequenceBarrier = ringBuffer.newBarrier(); MyEventHandler handler = new MyEventHandler(); BatchEventProcessor<ValueEvent> batchEventProcessor = new BatchEventProcessor<ValueEvent>(ringBuffer, sequenceBarrier, handler); ringBuffer.addGatingSequences(batchEventProcessor.getSequence()); ExecutorService executor = Executors.newSingleThreadExecutor(Executors.defaultThreadFactory); executor.submit(batchEventProcessor); final RingBuffer<ValueEvent> rb = ringBuffer; for (long i = 0; i < 100000000; i++) { long next = rb.next(); rb.get(next).setValue(i); rb.publish(next); } batchEventProcessor.halt(); System.out.println("cost:"+(System.currentTimeMillis() - cost)); } }
最終ArrayBlockingQueue需要越20秒,而disruptor僅2秒左右。
測試環境:
寫道
jdk7
主機名: WHITEME-PC
OS 名稱: Microsoft Windows 7 旗艦版
系統製造商: LENOVO
系統型號: INVALID
系統類型: x64-based PC
處理器: 安裝了 1 個處理器。
[01]: Intel64 Family 6 Model 37 Stepping 5 GenuineIntel ~2533 Mhz
BIOS 版本: LENOVO 2ECN29WW , 2010/9/21
物理內存總量: 3,957 MB
可用的物理內存: 987 MB
虛擬內存: 最大值: 7,911 MB
虛擬內存: 可用: 4,344 MB
虛擬內存: 使用中: 3,567 MB
主機名: WHITEME-PC
OS 名稱: Microsoft Windows 7 旗艦版
系統製造商: LENOVO
系統型號: INVALID
系統類型: x64-based PC
處理器: 安裝了 1 個處理器。
[01]: Intel64 Family 6 Model 37 Stepping 5 GenuineIntel ~2533 Mhz
BIOS 版本: LENOVO 2ECN29WW , 2010/9/21
物理內存總量: 3,957 MB
可用的物理內存: 987 MB
虛擬內存: 最大值: 7,911 MB
虛擬內存: 可用: 4,344 MB
虛擬內存: 使用中: 3,567 MB