参考demo:http://ifeve.com/disruptor-getting-started
public class LongEvent {
private long value;
public long getValue() {
return value;
}
public void setValue(long value) {
this.value = value;
}
}
/**
* 声明了一个EventFactory来实例化Event对象
* disruptor会使用这个工厂类来创建事件
*/
public class LongEventFactory implements EventFactory {
@Override
public Object newInstance() {
return new LongEvent();
}
}
//事件消费者,也就是一个事件处理器
public class LongEventHandler implements EventHandler<LongEvent> {
/**
* 具体的消费逻辑
* @param longEvent
* @param l
* @param b
*/
@Override
public void onEvent(LongEvent longEvent, long l, boolean b) {
System.out.println("获取到数据:"+longEvent.getValue());
}
}
import java.nio.ByteBuffer;
import com.lmax.disruptor.RingBuffer;
/**
* 很明显的是:当用一个简单队列来发布事件的时候会牵涉更多的细节,这是因为事件对象还需要预先创建。
* 发布事件最少需要两步:获取下一个事件槽并发布事件(发布事件的时候要使用try/finally保证事件一定会被发布)。
* 如果我们使用RingBuffer.next()获取一个事件槽,那么一定要发布对应的事件。
* 如果不能发布事件,那么就会引起Disruptor状态的混乱。
* 尤其是在多个事件生产者的情况下会导致事件消费者失速,从而不得不重启应用才能会恢复
* 在Disruptor3.0以后的版本最好使用Event Publisher或者Event Translator来发布事件。
*/
public class LongEventProducer {
private final RingBuffer<LongEvent> ringBuffer;
public LongEventProducer(RingBuffer<LongEvent> ringBuffer){
this.ringBuffer = ringBuffer;
}
/**
* onData用来发布事件,每调用一次就发布一次事件
* 它的参数会通过事件传递给消费者
*/
public void onData(ByteBuffer byteBuffer){
//1.可以把ringBuffer看做一个事件队列,那么next就是得到下面一个事件槽
long sequence = ringBuffer.next();
try {
//2.用上面的索引取出一个空的事件用于填充 (获取该序号对应的事件对象)此时的event对象成员变量还没有赋值
LongEvent event = ringBuffer.get(sequence);
//3.将真实业务数据设置给事件
event.setValue(byteBuffer.getLong(0));
} finally {
//4.发布事件
//注意,最后的ringBuffer.publish方法必须包含在finally中以确保必须得到调用,如果某个请求的sequence未被提交,将会堵塞后续的发布操作或者其它的producer。
ringBuffer.publish(sequence);
}
}
}
import java.nio.ByteBuffer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.YieldingWaitStrategy;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;
public class LongEventMain {
public static void main(String[] args) throws Exception {
//创建缓冲线程池
ExecutorService executor = Executors.newCachedThreadPool();
//创建事件工厂
LongEventFactory factory = new LongEventFactory();
//定义bufferSize ,也就是ringBuffer大小,必须是2的N次方
int ringBufferSize = 1024 * 1024;
//创建disruptor
//1、第一个参数为工厂类对象,用于创建一个个LongEvent实例,LongEvent是实际的消费数据
//2、第二个参数为缓冲区的大小
//3、第三个参数为线程池,进行Disruptor内部数据的接受处理调度
//4、第四个参数为ProducerType.SINGLE / ProducerType.MULTI,指定生产者是单个,还是多个的
//5、生产与消费时的策略,对生产和消费数据的快慢做一个协调
Disruptor<LongEvent> disruptor = new Disruptor<LongEvent>(factory, ringBufferSize, executor, ProducerType.SINGLE, new YieldingWaitStrategy());
// 连接消费事件方法
disruptor.handleEventsWith(new LongEventHandler());
// 启动
disruptor.start();
//发布事件
RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer();
//生产者,生产数据并放到ringBuffer中
LongEventProducer producer = new LongEventProducer(ringBuffer);
//LongEventProducerWithTranslator producer = new LongEventProducerWithTranslator(ringBuffer);
//8个空间的缓冲区
ByteBuffer byteBuffer = ByteBuffer.allocate(8);
for(long a = 0; a < 50; a++){
//把a放在ByteBuffer的第一个位置,一直循环覆盖
byteBuffer.putLong(0, a);
producer.onData(byteBuffer);
Thread.sleep(100);
}
//关闭 disruptor,方法会堵塞,直至所有的事件都得到处理
disruptor.shutdown();
//关闭 disruptor 使用的线程池,如果需要的话,必须手动关闭,disruptor在shutdown时不会自动关闭
executor.shutdown();
}
}
import java.nio.ByteBuffer;
import com.lmax.disruptor.EventTranslatorOneArg;
import com.lmax.disruptor.RingBuffer;
/**
* Disruptor 3.0提供了lambda式的API。这样可以把一些复杂的操作放在Ring Buffer,
* 所以在Disruptor3.0以后的版本最好使用Event Publisher或者Event Translator来发布事件
*/
public class LongEventProducerWithTranslator {
private final RingBuffer<LongEvent> ringBuffer;
//初始化环形数组ringBuffer
public LongEventProducerWithTranslator(RingBuffer<LongEvent> ringBuffer) {
this.ringBuffer = ringBuffer;
}
//一个translator可以看做一个事件初始化器,publicEvent方法会调用它
//填充Event
private static final EventTranslatorOneArg<LongEvent, ByteBuffer> translatorOneArg =
new EventTranslatorOneArg<LongEvent, ByteBuffer>() {
@Override
public void translateTo(LongEvent event, long sequence, ByteBuffer buffer) {
event.setValue(buffer.getLong(0));
}
};
public void onData(ByteBuffer buffer){
ringBuffer.publishEvent(translatorOneArg, buffer);
}
}