什么是LMAX干扰器设计模式?

时间:2013-01-31 16:48:18

标签: design-patterns disruptor-pattern

有人能用简单的例子告诉我什么是Disruptor设计模式?我想了解这种设计模式的基础知识。

3 个答案:

答案 0 :(得分:4)

一个简单的Google给了我很多信息,包括Martin Fowler的this introduction

  

在原始级别,您可以将Disruptor视为多播图   生产者在其上放置发送给所有人的对象的队列   消费者通过单独的下游队列进行并行消费。   当你向内看时,你会看到这个队列网络真的是一个   单数据结构 - 环形缓冲区。每个生产者和消费者都有   一个序列计数器,用于指示当前缓冲区中的哪个插槽   继续努力。每个生产者/消费者编写自己的序列计数器但是   可以阅读其他人的序列计数器。这样生产者就可以阅读   消费者的柜台,以确保它想要写入的插槽是   可以在柜台上没有任何锁定。同样,消费者也可以   确保它只在其他消费者完成后处理消息   通过观看柜台来看。

GitHub project包含Java代码+ doc。

答案 1 :(得分:3)

我花了几天的时间阅读它,并且刚刚开始在架构上掌握它,并且掌握了为什么这种设计模式出现的原因。

有关如何实现try https://github.com/trevorbernard/disruptor-examples

的简单代码示例

要获得一个很好的描述,包括白皮书,源代码和UML图表的链接,您可以尝试从 http://martinfowler.com/articles/lmax.html

答案 2 :(得分:2)

来自this article

  

disruptor模式是一个由循环备份的批处理队列   阵列(即环形缓冲区)充满预先分配的传输   使用 memory-barriers 同步生产者和对象的对象   消费者通过序列。

幸运的是,您不需要了解破坏者模式的内在细节才能使用它。如果您发现通过代码更容易理解,下面是CoralQueue Hello World ,这是一个用于实现破坏程序模式的线程间通信的超低延迟队列。

package com.coralblocks.coralqueue.sample.queue;

import com.coralblocks.coralqueue.AtomicQueue;
import com.coralblocks.coralqueue.Queue;
import com.coralblocks.coralqueue.util.Builder;

public class Basics {

    public static void main(String[] args) {

        final Queue<StringBuilder> queue = new AtomicQueue<StringBuilder>(1024, new Builder<StringBuilder>() {
            @Override
            public StringBuilder newInstance() {
                return new StringBuilder(1024);
            }
        });

        Thread producer = new Thread(new Runnable() {

            private final StringBuilder getStringBuilder() {
                StringBuilder sb;
                while((sb = queue.nextToDispatch()) == null) {
                    // queue can be full if the size of the queue
                    // is small and/or the consumer is too slow

                    // busy spin (you can also use a wait strategy instead)
                }
                return sb;
            }

            @Override
            public void run() {

                StringBuilder sb;

                while(true) { // the main loop of the thread

                    // (...) do whatever you have to do here...

                    // and whenever you want to send a message to
                    // the other thread you can just do:
                    sb = getStringBuilder();
                    sb.setLength(0);
                    sb.append("Hello!");
                    queue.flush();

                    // you can also send in batches to increase throughput:
                    sb = getStringBuilder();
                    sb.setLength(0);
                    sb.append("Hi!");

                    sb = getStringBuilder();
                    sb.setLength(0);
                    sb.append("Hi again!");

                    queue.flush(); // dispatch the two messages above...
                }
            }
        }, "Producer");

        Thread consumer = new Thread(new Runnable() {

            @Override
            public void run() {

                while (true) { // the main loop of the thread

                    // (...) do whatever you have to do here...

                    // and whenever you want to check if the producer
                    // has sent a message you just do:

                    long avail;
                    while((avail = queue.availableToPoll()) == 0) {
                        // queue can be empty!
                        // busy spin (you can also use a wait strategy instead)
                    }

                    for(int i = 0; i < avail; i++) {
                        StringBuilder sb = queue.poll();
                        // (...) do whatever you want to do with the data
                        // just don't call toString() to create garbage...
                        // copy byte-by-byte instead...
                    }
                    queue.donePolling();
                }
            }
        }, "Consumer");

        consumer.start();
        producer.start();
    }
}