Disruptor 实现无锁队列

来源:互联网 发布:淘宝商品迁徙 编辑:程序博客网 时间:2024/06/07 20:23

Disruptor

经大佬提醒发现的一个无锁环形队列的处理高并发的一个框架Disruptor,据不完整统计 单线程一秒可以有六百万的吞吐量,都得益于RungBuffer,打破了jvm的 内存屏障 调用cpu来执行的, 这里贴上参考网站:[并发网站](http://ifeve.com/disruptor/)    [github官网](http://lmax-exchange.github.io/disruptor/)接下来给出写的一个例子供参考一下!

1.通用得队列封装类重点内容

public class MsgEvent<T> {    /**     * 队列中实际bean     */    private T value;    public T getValue() {        return value;    }    public void setValue(T value) {        this.value = value;    }}

2.队列中预分配对象内存EventFactory,事件工厂

public class MsgEventFactory<T> implements EventFactory<MsgEvent<T>>{    @Override    public MsgEvent<T> newInstance() {        return new MsgEvent<T>();    }}

3.实体对象 Arithmetic(这里用对象的原因是更真是一点儿)

public class Arithmetic {    private long number;    public long getNumber() {        return number;    }    public void setNumber(long number) {        this.number = number;    }    public Arithmetic(long number) {        this.number = number;    }}

4.定义消费者

public class ArithmeticHandler implements EventHandler<MsgEvent<Arithmetic>> {    @Override    public void onEvent(MsgEvent<Arithmetic> event, long arg1, boolean arg2) throws Exception {        Arithmetic at = event.getValue();            if(at.getNumber() >=6024000)//这个6024000写死了 可以更改为实际数值            {                System.out.println("消费了一个" + at.getNumber() + ***********************************************");                System.out.println(System.currentTimeMillis());            }    }}

5.定义一个生产方法

public class ArithmeticProducer<T> {    /**     * disruptor.getRingBuffer()     */    private final RingBuffer<MsgEvent<T>> ringBuffer;    /**     * 构造器     * @param ringBuffer disruptor.getRingBuffer()     */    public ArithmeticProducer(RingBuffer<MsgEvent<T>> ringBuffer) {        this.ringBuffer = ringBuffer;    }    public void produce(T obj) {        long sequence = ringBuffer.next();        try {            MsgEvent<T> event = ringBuffer.get(sequence);            event.setValue(obj);        }finally{            ringBuffer.publish(sequence);        }    }}

6.事件执行方法:

public class ArithmeticMain {    public static void main(String[] args) {        int ringBufferSize = 1024;        //Executor executor = Executors.newCachedThreadPool();        MsgEventFactory<Arithmetic> msgEventFactory = new MsgEventFactory<Arithmetic>();        Disruptor<MsgEvent<Arithmetic>> disruptor = new Disruptor<MsgEvent<Arithmetic>>(msgEventFactory, ringBufferSize,                DaemonThreadFactory.INSTANCE, ProducerType.MULTI, new YieldingWaitStrategy());        ArithmeticHandler arithmeticHandler = new ArithmeticHandler();        disruptor.handleEventsWith(arithmeticHandler);        disruptor.start();        ArithmeticProducer<Arithmetic> ar = new ArithmeticProducer<Arithmetic>(disruptor.getRingBuffer());        System.out.println(System.currentTimeMillis());        for (int i = 1; i <= 6024000; i++) {            Arithmetic a = new Arithmetic(i);            ar.produce(a);        }    }}

这个main 中的 new YieldingWaitStrategy() 是一种等待策略
共有四种等待策略:
Disruptor 定义了 com.lmax.disruptor.WaitStrategy 接口用于抽象 Consumer 如何等待新事件,这是策略模式的应用。
Disruptor 提供了多个 WaitStrategy 的实现,每种策略都具有不同性能和优缺点,根据实际运行环境的 CPU 的硬件特点选择恰当的策略,并配合特定的 JVM 的配置参数,能够实现不同的性能提升。
例如,BlockingWaitStrategy、SleepingWaitStrategy、YieldingWaitStrategy 等,其中,
BlockingWaitStrategy 是最低效的策略,但其对CPU的消耗最小并且在各种不同部署环境中能提供更加一致的性能表现;
SleepingWaitStrategy 的性能表现跟 BlockingWaitStrategy 差不多,对 CPU 的消耗也类似,但其对生产者线程的影响最小,适合用于异步日志类似的场景;
YieldingWaitStrategy 的性能是最好的,适合用于低延迟的系统。在要求极高性能且事件处理线数小于 CPU 逻辑核心数的场景中,推荐使用此策略;例如,CPU开启超线程的特性。

我不是做原理分析的! 我只是把我写的一个小例子上传上来,应用场景应该稍作修改就可以使用的!或许哪位路人需要!仅此。。。

原创粉丝点击