美文网首页
Disruptor-02 再探

Disruptor-02 再探

作者: rock_fish | 来源:发表于2020-06-09 00:12 被阅读0次
    上期回顾

    Disruptor-01 初识中对Disruptor有了初步的认知,大概知道其核心组成元素以及核心运转流程,在所有的组成元素中,EventFactory作用不甚清晰,这一篇就来弄清楚EventFactory的作用。

    EventFactory什么时候用

    我们在代码中,加入一些日志信息

    public class LongEventFactory implements EventFactory<LongEvent>
    {
        public LongEvent newInstance()
        {
    
            LongEvent longEvent =  new LongEvent();
            System.out.println("new Event:" + longEvent.hashCode());
            return  longEvent;
        }
    }
    
         public static void main(String[] args) throws InterruptedException {
    
            // Executor that will be used to construct new threads for consumers
            Executor executor = Executors.newCachedThreadPool();
    
            // 事件工厂,用于创建event
            LongEventFactory factory = new LongEventFactory();
    
            // 指定ringbuf的大小,必须是2的整数倍
            int bufferSize = 4;
    
            // 构建一个 Disruptor
            Disruptor<LongEvent> disruptor = new Disruptor<>(factory, bufferSize, executor);
    
            System.out.println("..new Disruptor...");
            // 给disruptor中添加消费者
            disruptor.handleEventsWith(new LongEventHandler());
            System.out.println("..handleEventsWith...");
            // 启动disruptor
            disruptor.start();
            System.out.println("..start...");
    
            //-----------万事俱备,只欠消息(消息的生产者投递消息)
    
            // Get the ring buffer from the Disruptor to be used for publishing.
            RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer();
    
            LongEventProducer producer = new LongEventProducer(ringBuffer);
    
            // 跟blockqueue 比对一下
    
            for (long l = 0; l<12; l++)
            {
                long startAt = System.currentTimeMillis();
                producer.publishEvent(l);
                long endAt = System.currentTimeMillis();
                //System.out.println(endAt-startAt);
                //Thread.sleep(1000);
            }
        }
    
    new Event:801197928
    new Event:1495242910
    new Event:1711574013
    new Event:1631862159
    ..new Disruptor...
    ..handleEventsWith...
    ..start...
    

    通过以上日志信息,可明确在构建Disruptor的时候,会调用LongEventFactory#newInstance创建对象,队列多大,就预先创建多少个事件对象.

    此时我们的疑问是,这里预先创建这些对象什么作用呢?

    生产者重复使用预创建的事件对象

    通过以下日志信息可以看出,事件对象再循环反复使用;

    801197928
    1495242910
    1711574013
    1631862159
    ----------------LongEvent{value=0}
    ----------------LongEvent{value=1}
    ----------------LongEvent{value=2}
    ----------------LongEvent{value=3}
    801197928
    1495242910
    1711574013
    1631862159
    ----------------LongEvent{value=4}
    ----------------LongEvent{value=5}
    ----------------LongEvent{value=6}
    ----------------LongEvent{value=7}
    

    同时我们会开始留意translateTo这个方法的作用是,复用对象,仅变更对象中的属性值.

    /**
     * 复用对象,仅变更对象中的属性值
     */
    public class LongEventTranslator  implements EventTranslatorOneArg<LongEvent,Long> {
        @Override
        public void translateTo(LongEvent longEvent, long l, Long aLong) {
            System.out.println(longEvent.hashCode());
            longEvent.set(aLong);
        }
    }java
    
    • 第一个入参,是预创建的事件对象
    • 第二个参数,是序列号,知识后补
    • 第三个参数,是将待发送的消息内容,

    方法中关键逻辑是 通过longEvent.set(aLong),将消息内容aLong赋值给longEvent中的long类型变量.

    为什么要预创建对象,为什么要复用这些事件对象
    1. 避免对象的创建和销毁
      1.1 减少空间开销(内存)
      1.2 减少时间开销(new,GC的时间消耗)
    2. 连续的创建对象,会将对象放置在一段相对连续的内存空间中
      2.1 连续内存空间的读写,效率更高

    相关文章

      网友评论

          本文标题:Disruptor-02 再探

          本文链接:https://www.haomeiwen.com/subject/eofyzhtx.html