简体   繁体   English

如何使用干扰模式实现解复用器?

[英]How to implement a demultiplexer using the disruptor pattern?

I would like to have a ring buffer queue that will receive objects and distribute them across multiple threads from a thread pool, in a single producer to multiple consumers fashion. 我希望有一个环形缓冲区队列,该队列将以单个生产者方式向多个使用者方式接收对象并将它们分布在线程池中的多个线程之间。 How do I accomplish that using the disruptor pattern? 如何使用干扰者模式完成此任务? Any HelloDemux code example? 任何HelloDemux代码示例? Thanks!!! 谢谢!!!

This article details everything about demultiplexers implementing the disruptor pattern but I think a thread pool implies that you will need a dispatcher, which goes against the disruptor pattern. 本文详细介绍了实现解复用器模式的多路分解器,但我认为线程池意味着您将需要一个与该破坏器模式背道而驰的调度程序。 To implement a demux you setup a fixed number of consumer threads, not a pool, and let them grab the messages from the tail of the queue. 要实现多路分解,您需要设置固定数量的使用者线程(而不是池),并让它们从队列尾部获取消息。 Now, you might ask, how can they do that without a dispatcher? 现在,您可能会问,如果没有调度员,他们如何做到这一点? They simply busy spin (or use some other kind of wait strategy that is a combination of spinning, yielding, parking, sleeping, etc.) around the queue tail. 他们只是在队列尾部忙于旋转(或使用其他类型的等待策略,这些策略是旋转,屈服,停车,睡觉等的组合)。 Now, you might ask, how can they do that without stepping into each other? 现在,您可能会问,他们如何才能做到彼此之间互不干涉? Then you have two options: you can use MODULUS (lock-free) or CAS (light lock). 然后,您有两个选择:您可以使用MODULUS(无锁)或CAS(轻锁)。 Each one has its own advantages and disadvantages. 每个人都有自己的优点和缺点。 MODULUS is fast but can cause lane contention if one consumer falls behind. MODULUS速度很快,但是如果一个消费者落后,则可能导致通道争用。 CAS is not as fast but does not cause lane contention. CAS速度不快,但不会引起通道争用。

package com.coralblocks.coralqueue.sample.demux;

import com.coralblocks.coralqueue.demux.CASAtomicDemux;
import com.coralblocks.coralqueue.demux.Demux;

public class Sample {

    private static final int NUMBER_OF_CONSUMERS = 4;

    public static void main(String[] args) throws InterruptedException {

        final Demux<StringBuilder> queue = new CASAtomicDemux<StringBuilder>(1024, StringBuilder.class, NUMBER_OF_CONSUMERS);

        Thread[] consumers = new Thread[NUMBER_OF_CONSUMERS];

        for(int i = 0; i < consumers.length; i++) {

            final int index = i;

            consumers[i] = new Thread() {

                @Override
                public void run() {

                    boolean running = true;

                    while(running) {
                        long avail;
                        while((avail = queue.availableToPoll(index)) == 0); // busy spin
                        for(int i = 0; i < avail; i++) {
                            StringBuilder sb = queue.poll(index);

                            if (sb == null) break; // mandatory for demuxes!

                            if (sb.length() == 0) {
                                running = false;
                                break; // exit immediately...
                            } else {
                                System.out.println(sb.toString());
                            }
                        }
                        queue.donePolling(index);
                    }
                }
            };

            consumers[i].start();
        }

        StringBuilder sb;

        for(int i = 0; i < 10; i++) {
            while((sb = queue.nextToDispatch()) == null); // busy spin
            sb.setLength(0);
            sb.append("message ").append(i);
            queue.flush();
        }

        // send a message to stop consumers...
        for(int i = 0; i < NUMBER_OF_CONSUMERS; i++) {
            // because the consumer exit immediately on this message, each
            // consumer will get one of these messages and exit...
            while((sb = queue.nextToDispatch()) == null); // busy spin
            sb.setLength(0);
        }
        queue.flush(); // sent batch

        for(int i = 0; i < consumers.length; i++) consumers[i].join();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM