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
本文对比了Disruptor与ArrayBlockingQueue在典型生产者-消费者问题中的性能表现,结果显示Disruptor在作者的测试环境中比ArrayBlockingQueue快近10倍。
809





