Why my Disruptor program don't take full advantage of the ringbuffer

别说谁变了你拦得住时间么 提交于 2019-12-02 13:41:37

问题


Disruptor github address is: https://github.com/LMAX-Exchange/disruptor

I've a simple test for it as below:

public class DisruptorMain {
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static void main(String[] args) throws Exception {
        class Element {

            private int value;

            public int get() {
                return value;
            }

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

        }

        ThreadFactory threadFactory = new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r, "simpleThread");
            }
        };

        EventFactory<Element> factory = new EventFactory<Element>() {
            @Override
            public Element newInstance() {
                return new Element();
            }
        };

        EventHandler<Element> handler = new EventHandler<Element>() {
            @Override
            public void onEvent(Element element, long sequence, boolean endOfBatch) {
                try {
                    Thread.sleep(1000 * sequence);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println("Element: " + element.get());
            }
        };

        BlockingWaitStrategy strategy = new BlockingWaitStrategy();

        int bufferSize = 4;

        Disruptor<Element> disruptor = new Disruptor(factory, bufferSize, threadFactory, ProducerType.SINGLE, strategy);

        disruptor.handleEventsWith(handler);

        disruptor.start();

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

        for (int l = 0; l < 8; l++) {
            long sequence = ringBuffer.next();
            System.out.println("sequence:" + sequence);

            try {
                Element event = ringBuffer.get(sequence);
                event.set(l);
            } finally {
                ringBuffer.publish(sequence);
            }
        }
    }
}

The result is: sequence:0 sequence:1 sequence:2 sequence:3 Element: 0 Element: 1 Element: 2 Element: 3 sequence:4 sequence:5 sequence:6 sequence:7 Element: 4 Element: 5 Element: 6 Element: 7

in my test, I've defined a ringbuffer size of 4, and I have a producer to create 8 tasks for it, my question is, when the producer have put 4 tasks in the ringbuffer, the consumer begins to take task from the ringbuffer to work, after task 1 finish, the ringbuffer should have an empty space for the task 5, but the result shows that, only if all of the tasks have been finished in the ringbuffer, the ringbuffer can accept the new task, why?


回答1:


This is because the Disruptor will batch in the event handler. If the event handler is slow or the ring buffer is small the batch size can often be the size of the ring buffer. The Disruptor will only update the processed sequence for that event handler until the batch is complete. This reduces the number of updates that it needs to make to the sequence variable used by the publisher to determine if space is available. If you need to make space available earlier than the default then you can do that using a SequenceReportingEventHandler.

public class MyEventHandler implements SequenceReportingEventHandler<Element> {
    Sequence processedSequence;

    public void setSequenceCallback(Sequence s) {
        processedSequence = s;
    }

    public void onEvent(Element e, long sequence, boolean endOfBatch) {
        // Do stuff
        processedSequence.set(sequence);
    }
}


来源:https://stackoverflow.com/questions/48352411/why-my-disruptor-program-dont-take-full-advantage-of-the-ringbuffer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!