直接拜读大佬文章:
架构师系列-并发框架Disruptor(一)- 入门
架构师系列-并发框架Disruptor(二)- 高性能原理
架构师系列-并发框架Disruptor(三)- 高级使用
概念梳理
Disruptor:一个JVM中多个线程之间的消息队列
RingBuffer:环形缓冲区。逻辑意义上的一个环:数组实现的先进先出的缓冲区。生产者和消费者之间交换数据的桥梁
Sequence:序号。数据的位置,包含生产消息的内存位置以及消费的offset
Sequencer:序号生成器。返回生产消息的位置(即序号)
Sequence Barrier:序号屏障。通过控制序号来实现屏障。(通过内置的生产者和消费者序号来协调“数据交换”)屏障的目的:控制消费者的消费位置,不能随意消费任意位置的消息。
Wait Strategy:消费者等待生产消息的策略
Event:传递的数据类,用户自定义
EventHandler:消费者,用户自定义
Producer:生产者,调用 Disruptor 发布事件。
简单使用
1.引入依赖
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.4.4</version>
</dependency>
2.使用示例代码
Disruptor<自定义传递数据类> disruptor = new Disruptor(new EventFactory(),//传递数据的工厂类,自定义,实现EventFactory接口即可
1 << 16, //RingBufferSize
Executors.defaultThreadFactory(), //线程工厂类
clientNums > 1 ? ProducerType.MULTI : ProducerType.SINGLE, //生产者类型。单线程/多线程
new SleepingWaitStrategy()); //消费者等待策略。com.lmax.disruptor.WaitStrategy
//定义消费者。自定义,实现EventHandler接口即可
disruptor.handleEventsWith(new EventsHandler())
//EventsHandler 执行之后执行ClearEventHandler
.then(new ClearEventHandler());
disruptor.start();
3.生产消息 (两种方式)
方法一:直接拿到RingBuffer,使用RingBuffer的pulish方法(注意并发问题)
RingBuffer<自定义传递数据类> ringBuffer = disruptor.getRingBuffer()
//拿到下一数据位置
long sequence = ringBuffer.next();
try{
//拿到位置上的数据
自定义传递数据类 selfData = ringBuffer.get(sequence);
//将想上传的数据写入
selfData.setMessage(message);
selfData.setSequence(sequence);
} catch (Exception ex){
log.warn("消息加入到生产中失败:", ex);
} finally {
//数据发布
ringBuffer.publish(sequence);
}
方法二:Disruptor提供的交换类EventTranslatorOneArg,使用RingBuffer的pulishEvent方法
public class LongEventProducerWithTranslator {
private final RingBuffer<自定义传递数据类> ringBuffer;
public LongEventProducerWithTranslator(RingBuffer<自定义传递数据类> ringBuffer) {
this.ringBuffer = ringBuffer;
}
private static final EventTranslatorOneArg<自定义传递数据类, Long> TRANSLATOR =
new EventTranslatorOneArg<自定义传递数据类, 处理数据类型>() {
public void translateTo(自定义传递数据类 event, long sequence, 处理数据类型 data) {
//sequence 为当前 event的序号
event.set(data);
}
};
public void onData(Long data) {
ringBuffer.publishEvent(TRANSLATOR, data);
}