Java 线程间通讯库 Disruptor

来源:互联网 发布:小米手机怎么迁移数据 编辑:程序博客网 时间:2024/06/08 13:17

Disruptor的具体原理  http://ifeve.com/disruptor/


通过cache line对齐来解决 false sharing的问题,而且是无锁的,应该比java自带的blocking queue速度要快。


这个Disruptor库用来解决生产者和消费者问题,它可以实现生产者和消费者  N:M的关系。

可实现的模式有 菱形(disruptor.handleEventsWith(c0,c1).then(c2) )

 *
 *               +----+
 *    +----->| C0 |-----+
 *    |          +----+     |
 *    |                 v
 * +----+               +----+
 * | P0 |                | C2 |
 * +----+               +----+
 *    |                 ^
 *    |          +----+     |
 *    +----->| C1 |-----+
 *              +----+
 *

管道(isruptor.handleEventsWith(c0).then(c1).then(c2))

 * +----+     +----+     +----+      +----+
 * | P0 |--->| C0 |--->| C1 |--->| C2 |
 * +----+    +----+      +----+      +----+


    后面的消费者要等到前面的消费者处理完后,才会处理该消息。菱形状态下,C0和C1并发运行,但处理的消息都是一样的。也就是说,一个生产者产生的同一个数据都会被

C0和C1处理,而不会只有C0或者C1处理。并行的意思是C0,C1,C2在不同的线程中。disruptor会为每个消费者分配一个线程。

     要注意ringbuffer的分配的大小,ringbuffer不应该太大。如果你需要一个很大的ringbuffer,说明消费者线程这边处理能力不够,需要提高消费者处理线程能力。

当然也有可能是生产者这边burst的比较厉害。消费者消费完数据后,ringbuffer仍旧引用你的数据,导致Jvm无法回收这些内存。如果确实为应对生产者的burst,而

申请一个大的ringbuffer,注意在Evnet中清理数据。这个可以通过加一个消费者,最后一个消费者处理event中引用的数据即可。


MainDisruptor.java

package example1;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ThreadFactory;import com.lmax.disruptor.BlockingWaitStrategy;import com.lmax.disruptor.dsl.Disruptor;import com.lmax.disruptor.dsl.ProducerType;public class MainDisruptor {public static void main(String[] args) {// TODO Auto-generated method stub//ExecutorService executor = Executors.newFixedThreadPool(1);Disruptor<LogEvent> disruptor = new Disruptor<LogEvent>(new MyFactory(), 4, new ThreadFactory() {@Overridepublic Thread newThread(Runnable r) {Thread t = new Thread(r);System.out.println("create new thread " + t.getId());return t;}}, ProducerType.SINGLE,new BlockingWaitStrategy());new MyEventHandler(0);//产生三个消费者线程disruptor.handleEventsWith( new MyEventHandler(0),  new MyEventHandler(1) ).then( new MyEventHandler(3));disruptor.start();for(int i=0; i<10; i++) {MyData data = new MyData();data.orderID = i;data.price = Math.random();disruptor.publishEvent( new MyEventTranslatorOneArg(), data);}disruptor.shutdown();}}



LogEvent.java

public class LogEvent {private MyData data;public void setValue(MyData data) {this.data = data;}public MyData getData() {return this.data;}public String toString() {return "LogEvent";}}

MyData.java

public class MyData {public int orderID;public double price;public String toString() {return String.format("orderID %d, price %f", orderID, price); }}


MyEventHandler.java

import com.lmax.disruptor.EventHandler;public class MyEventHandler implements EventHandler<LogEvent> {private int tag;public MyEventHandler(int tag) {this.tag = tag;}@Overridepublic void onEvent(LogEvent event, long sequence, boolean endofBatch) throws Exception {// TODO Auto-generated method stubSystem.out.println("onEvent " + sequence + " tag " + this.tag + " threadID " + Thread.currentThread().getId() + "  " + endofBatch);}}

MyEventTranslatorOneArg.java


import com.lmax.disruptor.EventTranslatorOneArg;public class MyEventTranslatorOneArg implements EventTranslatorOneArg<LogEvent, MyData> {@Overridepublic void translateTo(LogEvent event, long sequence, MyData data) {System.out.println(" assit publish event sequence " + sequence + "  threadID " + Thread.currentThread().getId());event.setValue(data);}}

MyFactory.java

import com.lmax.disruptor.EventFactory;public class MyFactory implements EventFactory<LogEvent> {@Overridepublic LogEvent newInstance() {// TODO Auto-generated method stubreturn new LogEvent();}}



原创粉丝点击