网上看了很多资料,很多都说到了多消费者,但没有找到多消费者并行消费不同事件消息,自己于是抽出了一下午时间研究了一下,具体代码实现如下(实例代码根据官方的git更改,本文基于3.3.6最新版本):
//定义时间工厂
LongEventFactory factory = new LongEventFactory();
//定义初始化ringBuffer大小,创建ringBuffer的时候会根据这个大小进行预先填充
int bufferSize = 16;
//定义线程池
Executor threadPool = Executors.newCachedThreadPool();
//创建ringBuffer
RingBuffer<LongEvent> ringBuffer = RingBuffer.create(ProducerType.SINGLE, factory, bufferSize,
new SleepingWaitStrategy());
//创建一个事件生产者
LongEventProducer producer = new LongEventProducer(ringBuffer);
int i = 1;
while (i++ <= bufferSize) {
//发布一个事件
producer.onData();
}
SequenceBarrier sequenceBarrier = ringBuffer.newBarrier();
//重点是这个消费序列,所有的消费者处理都必须共享一个消费序列
Sequence consumerSequence = new Sequence(-1);
//定义事件处理
LongEventHandler eventHandler = new LongEventHandler("测试1");
WorkProcessor<LongEvent> wp1 = new WorkProcessor<LongEvent>(ringBuffer, sequenceBarrier, eventHandler, eventHandler, consumerSequence);
//执行处理线程
threadPool.execute(wp1);
WorkProcessor<LongEvent> wp2 = new WorkProcessor<LongEvent>(ringBuffer, sequenceBarrier, eventHandler, eventHandler, consumerSequence);
threadPool.execute(wp2);
WorkProcessor<LongEvent> wp3 = new WorkProcessor<LongEvent>(ringBuffer, sequenceBarrier, eventHandler, eventHandler, consumerSequence);
threadPool.execute(wp3);
WorkProcessor<LongEvent> wp4 = new WorkProcessor<LongEvent>(ringBuffer, sequenceBarrier, eventHandler, eventHandler, consumerSequence);
threadPool.execute(wp4);
注意:以上所有的WorkProcessor都共享了一个consumerSequence,所以他们在从ringBuffer里面取数据的时候,不会出现取出同一事件发布的数据;
WorkProcessor的run方法关键源码如下:
do{
//这个workSequence就是我们前面传进来的consumerSequence
nextSequence = workSequence.get() + 1L;
sequence.set(nextSequence - 1L);
}
//这个地方会使用CAS的方法保证每次都是递增
while (!workSequence.compareAndSet(nextSequence - 1L, nextSequence));
测试结果如下:
4个线程共同消费事件,未出现同一个事件被两个线程同时消费
相关连接:https://github.com/LMAX-Exchange/disruptor