随笔 - 1357  文章 - 0  评论 - 1104  阅读 - 1941万

Disruptor多个消费者不重复处理生产者发送过来的消息

1、定义事件
事件(Event)就是通过 Disruptor 进行交换的数据类型。

复制代码
package com.ljq.disruptor;

import java.io.Serializable;

/**
 * 定义事件数据,本质是个普通JavaBean
 * 
 * @author jqlin
 */
@SuppressWarnings("serial")
public class LongEvent implements Serializable {
    private long value;

    public LongEvent() {
        super();
    }

    public LongEvent(long value) {
        super();
        this.value = value;
    }

    public long getValue() {
        return value;
    }

    public void setValue(long value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "LongEvent [value=" + value + "]";
    }
    
    
}
复制代码

 

2、LongEvent事件生产者

复制代码
package com.ljq.disruptor;

import com.lmax.disruptor.RingBuffer;

/**
 * LongEvent事件生产者,生产LongEvent事件 
 * 
 * @author jqlin
 */
public class LongEventProducer {
    private final RingBuffer<LongEvent> ringBuffer;

    public LongEventProducer(RingBuffer<LongEvent> ringBuffer) {
        this.ringBuffer = ringBuffer;
    }

    public void produceData(long value) {
        long sequence = ringBuffer.next(); // 获得下一个Event槽的下标
        try {
            // 给Event填充数据
            LongEvent event = ringBuffer.get(sequence);
            event.setValue(value);
            
        } finally {
            // 发布Event,激活观察者去消费, 将sequence传递给该消费者
            // 注意,最后的 ringBuffer.publish() 方法必须包含在 finally 中以确保必须得到调用;如果某个请求的 sequence 未被提交,将会堵塞后续的发布操作或者其它的 producer。
            ringBuffer.publish(sequence);
        }
    }
}
复制代码

 

3、LongEvent事件消息者

复制代码
package com.ljq.disruptor;

import com.lmax.disruptor.WorkHandler;

/**
 * LongEvent事件消息者,消息LongEvent事件
 * 
 * @author Administrator
 *
 */
public class LongEventConsumer  implements WorkHandler<LongEvent> {
    
    @Override
    public void onEvent(LongEvent event) throws Exception {
        System.out.println("consumer:" + Thread.currentThread().getName() + " Event: value=" + event.getValue() );
    }

}
复制代码

 

4、ProducerConsumerMain 
消费者-生产者启动类,其依靠构造Disruptor对象,调用start()方法完成启动线程。

复制代码
package com.ljq.disruptor;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.lmax.disruptor.EventFactory;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.SequenceBarrier;
import com.lmax.disruptor.WorkerPool;
import com.lmax.disruptor.YieldingWaitStrategy;
import com.lmax.disruptor.dsl.ProducerType;

/**
 *  Disruptor多个消费者不重复处理生产者发送过来的消息 
 * 
 * @author Administrator
 *
 */
public class ProducerConsumerMain {
    public static void main(String[] args) throws InterruptedException {
        Long time = System.currentTimeMillis();
        
        // 指定 ring buffer字节大小,必需为2的N次方(能将求模运算转为位运算提高效率 ),否则影响性能
        int bufferSize = 1024 * 1024;;
        //固定线程数
        int nThreads = 10;
        
        ExecutorService executor = Executors.newFixedThreadPool(nThreads);
     
        EventFactory<LongEvent> factory = new EventFactory<LongEvent>() {
            @Override
            public LongEvent newInstance() {
                return new LongEvent();
            }
        };
        
        // 创建ringBuffer
        RingBuffer<LongEvent> ringBuffer = RingBuffer.create(ProducerType.MULTI, factory, bufferSize,  new YieldingWaitStrategy());
        SequenceBarrier barriers = ringBuffer.newBarrier();
        // 创建10个消费者来处理同一个生产者发送过来的消息(这10个消费者不重复消费消息)
        LongEventConsumer[] consumers = new LongEventConsumer[50];
        for (int i = 0; i < consumers.length; i++) {
            consumers[i] = new LongEventConsumer();
        }
        WorkerPool<LongEvent> workerPool = new WorkerPool<LongEvent>(ringBuffer, barriers, 
                new EventExceptionHandler(), consumers);
        ringBuffer.addGatingSequences(workerPool.getWorkerSequences());
        workerPool.start(executor);

        LongEventProducer producer = new LongEventProducer(ringBuffer);
        for (int i = 0; i < 20000; i++) {
            producer.produceData(i);
        }
        
        Thread.sleep(1000); //等上1秒,等消费都处理完成
        workerPool.halt(); //通知事件(或者说消息)处理器 可以结束了(并不是马上结束!!!) 
        executor.shutdown(); 
        System.out.println("总共耗时(单位毫秒) :" + (System.currentTimeMillis() - time));
    }
}
复制代码

 

5、EventExceptionHandler

复制代码
package com.ljq.disruptor;

import com.lmax.disruptor.ExceptionHandler;

public class EventExceptionHandler implements ExceptionHandler {

    @Override
    public void handleEventException(Throwable ex, long sequence, Object event) {
        System.out.println("handleEventException:" + ex);
    }

    @Override
    public void handleOnShutdownException(Throwable ex) {
        System.out.println("handleEventException:" + ex);
    }

    @Override
    public void handleOnStartException(Throwable ex) {
        System.out.println("handleOnStartException:" + ex);
    }
     
}
复制代码

 

posted on   Ruthless  阅读(3566)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示