使用Disruptor的几个代码演示

原文链接:http://www.dubby.cn/detail.html?id=9052

代码地址:https://github.com/dubby1994/disruptor-demo

关于Disruptor的原理,实在是太过复杂,限于我水平有限,这里就不一一展开。如果读者有兴趣,可以去看他们的官方文档,代码库已迁移到GitHub,https://github.com/LMAX-Exchange/disruptor/wiki/Getting-Started,如果想看中文翻译,可以直接去看并发编程网,但是这个中文翻译时,版本较低,看的时候,部分术语,方法名,甚至类名都和新版的不太一致,阅读时请注意。在这里,仅仅给出几个实例代码。

1. 编码准备

1.1 版本依赖

<dependency>
    <groupId>com.lmax</groupId>
    <artifactId>disruptor</artifactId>
    <version>3.3.7</version>
</dependency>

1.2 Java版本

1.8

1.3 公用的一些类

定义的消息格式LongEvent.java

package cn.dubby.disruptor.wizard;

/**
 * Created by teeyoung on 17/10/27.
 */
public class LongEvent {
    private long value;

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

    public long getValue() {
        return value;
    }
}

把输入对象翻译成消息消息对象Translator.java

package cn.dubby.disruptor.wizard;

import com.lmax.disruptor.EventTranslatorOneArg;

import java.nio.ByteBuffer;

/**
 * Created by teeyoung on 17/10/27.
 */
class Translator implements EventTranslatorOneArg<LongEvent, ByteBuffer> {
    @Override
    public void translateTo(LongEvent event, long sequence, ByteBuffer data) {
        event.set(data.getLong(0));
    }
}

一个消息消费者LongEventHandler.java

package cn.dubby.disruptor.basic;

import com.lmax.disruptor.EventHandler;

/**
 * Created by teeyoung on 17/10/27.
 */
public class LongEventHandler implements EventHandler<LongEvent> {
    public void onEvent(LongEvent event, long sequence, boolean endOfBatch) {
        System.out.println("Event: " + event.getValue());
    }
}

2. 简单示例

2.1 单生产者,单消费者

SingleProductorLongEventMain.java

package cn.dubby.disruptor.basic;

import com.lmax.disruptor.BlockingWaitStrategy;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;

import java.nio.ByteBuffer;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * Created by teeyoung on 17/10/27.
 */
public class SingleProductorLongEventMain {

    private static final Translator TRANSLATOR = new Translator();

    public static void main(String[] args) throws Exception {
        // Executor that will be used to construct new threads for consumers
        Executor executor = Executors.newCachedThreadPool();

        // Specify the size of the ring buffer, must be power of 2.
        int bufferSize = 1024;

        // Construct the Disruptor
        Disruptor<LongEvent> disruptor = new Disruptor<LongEvent>(LongEvent::new, bufferSize, executor, ProducerType.SINGLE, new BlockingWaitStrategy());

        // Connect the handler
        disruptor.handleEventsWith(new LongEventHandler());

        // Start the Disruptor, starts all threads running
        disruptor.start();

        // Get the ring buffer from the Disruptor to be used for publishing.
        RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer();

        ByteBuffer bb = ByteBuffer.allocate(8);
        for (long l = 0; l < 10; l++) {
            bb.putLong(0, l);
            ringBuffer.publishEvent(TRANSLATOR, bb);
            Thread.sleep(100);
        }
    }

}

这里bufferSize的解释是the size of the ring buffer, must be power of 2.,也就是你所定义的ringbuffer的大小,必须是2的幂。

这里还需要注意的一个地方,那就是新版的Disruptor不建议我们使用Executor,而使用ThreadFactory代替。

可以简单的换成:

ThreadFactory threadFactory = new ThreadFactory() {
    private final AtomicInteger index = new AtomicInteger(1);
    @Override
    public Thread newThread(Runnable r) {
        return new Thread((ThreadGroup) null, r, "disruptor-thread-" + index.getAndIncrement());
    }
};

Disruptor<LongEvent> disruptor = new Disruptor<LongEvent>(LongEvent::new, bufferSize, threadFactory, ProducerType.SINGLE, new BlockingWaitStrategy());

结果:

2.2 多生产者,单消费者

MultiProductorLongEventMain.java

package cn.dubby.disruptor.basic;

import com.lmax.disruptor.BlockingWaitStrategy;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;

import java.nio.ByteBuffer;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * Created by teeyoung on 17/10/27.
 */
public class MultiProductorLongEventMain {

    private static final Translator TRANSLATOR = new Translator();

    public static void main(String[] args) throws Exception {
        // Executor that will be used to construct new threads for consumers
        Executor executor = Executors.newCachedThreadPool();

        // Specify the size of the ring buffer, must be power of 2.
        int bufferSize = 1024;

        // Construct the Disruptor
        Disruptor<LongEvent> disruptor = new Disruptor<LongEvent>(LongEvent::new, bufferSize, executor, ProducerType.MULTI, new BlockingWaitStrategy());

        // Connect the handler
        disruptor.handleEventsWith(new LongEventHandler());

        // Start the Disruptor, starts all threads running
        disruptor.start();

        // Get the ring buffer from the Disruptor to be used for publishing.
        new Thread(){
            @Override
            public void run() {
                RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer();

                ByteBuffer bb = ByteBuffer.allocate(8);
                for (long l = 0; l < 10; l++) {
                    bb.putLong(0, l);
                    ringBuffer.publishEvent(TRANSLATOR, bb);

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
        new Thread(){
            @Override
            public void run() {
                RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer();

                ByteBuffer bb = ByteBuffer.allocate(8);
                for (long l = 10; l < 20; l++) {
                    bb.putLong(0, l);
                    ringBuffer.publishEvent(TRANSLATOR, bb);

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
        new Thread(){
            @Override
            public void run() {
                RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer();

                ByteBuffer bb = ByteBuffer.allocate(8);
                for (long l = 20; l < 30; l++) {
                    bb.putLong(0, l);
                    ringBuffer.publishEvent(TRANSLATOR, bb);

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();

    }
}

这里使用三个线程同时生产。

结果:

3. 领域特定语言(DSL)

3.1 简单的消费者依赖关系

这张图的意思就是消费者3消费时,必须保证消费者1和消费者2已经完成对该消息的消费。举个例子,在处理实际的业务逻辑(C3)之前,需要校验数据(C1),以及将数据写入磁盘(C2)。

DisruptorWizardMain.java

package cn.dubby.disruptor.wizard;

import com.lmax.disruptor.EventHandler;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;

import java.nio.ByteBuffer;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * Created by teeyoung on 17/10/28.
 */
public class DisruptorWizardMain {

    private static final Translator TRANSLATOR = new Translator();

    public static void main(String[] args) throws InterruptedException {
        Executor executor = Executors.newCachedThreadPool();
        int bufferSize = 1024;

        EventHandler handler1 = new EventHandler<LongEvent>() {

            @Override
            public void onEvent(LongEvent event, long sequence, boolean endOfBatch) throws Exception {
                System.out.println("handler1 : " + event.getValue());
            }
        };
        EventHandler handler2 = new EventHandler<LongEvent>() {

            @Override
            public void onEvent(LongEvent event, long sequence, boolean endOfBatch) throws Exception {
                System.out.println("handler2 : " + event.getValue());
            }
        };

        EventHandler handler3 = new EventHandler<LongEvent>() {

            @Override
            public void onEvent(LongEvent event, long sequence, boolean endOfBatch) throws Exception {
                System.out.println("handler3 : " + event.getValue() + " arrived. Handler1 and handler2 should have completed. Completed.\n");
            }
        };

        Disruptor<LongEvent> disruptor = new Disruptor<>(LongEvent::new, bufferSize, executor);

        disruptor.handleEventsWith(handler1, handler2).then(handler3);

        disruptor.start();

        RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer();

        ByteBuffer bb = ByteBuffer.allocate(8);
        for (long l = 0; true; l++) {
            bb.putLong(0, l);
            ringBuffer.publishEvent(TRANSLATOR, bb);
            Thread.sleep(1000);
        }
    }
}

这里主要关注disruptor.handleEventsWith(handler1, handler2).then(handler3);定义了先让1和2消费,然后才能让2消费。
运行结果:

3.1 复杂的消费者依赖关系

这张图的意思就是消费者1b消费时,必须保证消费者1a已经完成对该消息的消费;消费者2b消费时,必须保证消费者2a已经完成对该消息的消费;消费者c3消费时,必须保证消费者1b和2b已经完成对该消息的消费。

DisruptorWizardMain2.java

package cn.dubby.disruptor.wizard;

import com.lmax.disruptor.EventHandler;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;

import java.nio.ByteBuffer;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * Created by teeyoung on 17/10/28.
 */
public class DisruptorWizardMain2 {

    private static final Translator TRANSLATOR = new Translator();

    public static void main(String[] args) throws InterruptedException {
        Executor executor = Executors.newCachedThreadPool();
        int bufferSize = 1024;

        EventHandler h1a = new EventHandler<LongEvent>() {

            @Override
            public void onEvent(LongEvent event, long sequence, boolean endOfBatch) throws Exception {
                System.out.println("h1a : " + event.getValue());
            }
        };
        EventHandler h1b = new EventHandler<LongEvent>() {

            @Override
            public void onEvent(LongEvent event, long sequence, boolean endOfBatch) throws Exception {
                System.out.println("h1b : " + event.getValue() + " arrived. H1a should have completed. Completed.");
            }
        };

        EventHandler h2a = new EventHandler<LongEvent>() {

            @Override
            public void onEvent(LongEvent event, long sequence, boolean endOfBatch) throws Exception {
                System.out.println("h2a : " + event.getValue());
            }
        };
        EventHandler h2b = new EventHandler<LongEvent>() {

            @Override
            public void onEvent(LongEvent event, long sequence, boolean endOfBatch) throws Exception {
                System.out.println("h2b : " + event.getValue() + " arrived. H2a should have completed. Completed.");
            }
        };

        EventHandler lastHandler = new EventHandler<LongEvent>() {

            @Override
            public void onEvent(LongEvent event, long sequence, boolean endOfBatch) throws Exception {
                System.out.println("lastHandler : " + event.getValue() + " arrived. H1a, h1b, h2a and h2b should have completed. Completed.\n");
            }
        };

        Disruptor<LongEvent> disruptor = new Disruptor<>(LongEvent::new, bufferSize, executor);

        disruptor.handleEventsWith(h1a, h2a);
        disruptor.after(h1a).then(h1b);
        disruptor.after(h2a).then(h2b);
        disruptor.after(h1b, h2b).then(lastHandler);

        disruptor.start();

        RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer();

        ByteBuffer bb = ByteBuffer.allocate(8);
        for (long l = 0; true; l++) {
            bb.putLong(0, l);
            ringBuffer.publishEvent(TRANSLATOR, bb);
            Thread.sleep(1000);
        }
    }
}

其中主要关注

disruptor.handleEventsWith(h1a, h2a);
disruptor.after(h1a).then(h1b);
disruptor.after(h2a).then(h2b);
disruptor.after(h1b, h2b).then(lastHandler);

这就是领域特定语言(DSL),定义了消费顺序。
结果:

微信扫码关注订阅号,获取更多精彩内容

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的 Java Disruptor 代码示例: ```java import com.lmax.disruptor.RingBuffer; import com.lmax.disruptor.dsl.Disruptor; import java.nio.ByteBuffer; import java.util.concurrent.Executor; import java.util.concurrent.Executors; public class LongEvent { private long value; public void set(long value) { this.value = value; } } class LongEventFactory implements EventFactory<LongEvent> { public LongEvent newInstance() { return new LongEvent(); } } class LongEventHandler implements EventHandler<LongEvent> { public void onEvent(LongEvent event, long sequence, boolean endOfBatch) { System.out.println("Event: " + event); } } public class DisruptorExample { public static void main(String[] args) { Executor executor = Executors.newCachedThreadPool(); LongEventFactory factory = new LongEventFactory(); int bufferSize = 1024; Disruptor<LongEvent> disruptor = new Disruptor<>(factory, bufferSize, executor); disruptor.handleEventsWith(new LongEventHandler()); RingBuffer<LongEvent> ringBuffer = disruptor.start(); ByteBuffer bb = ByteBuffer.allocate(8); for (long l = 0; true; l++) { bb.putLong(0, l); ringBuffer.publishEvent(new EventTranslatorOneArg<LongEvent, ByteBuffer>() { public void translateTo(LongEvent event, long sequence, ByteBuffer arg0) { event.set(arg0.getLong(0)); } }, bb); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } ``` 该代码使用 LMAX Disruptor 实现了一个简单的事件处理程序。Disruptor 可以高效地处理并发事件处理任务,例如高性能日志记录、消息传递和网络通信。在这个例子中,我们定义了一个事件对象 LongEvent,包含一个 long 值。我们使用 LongEventFactory 为 Disruptor 创建新的事件对象,使用 LongEventHandler 处理事件。我们还定义了一个 ByteBuffer,用于在主线程中创建事件并将其发布到 Disruptor 中。在主线程中,我们每秒钟创建一个新事件并将其发布到 Disruptor 中。在事件处理程序中,我们简单地打印事件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值