欢送拜访我的GitHub
https://github.com/zq2599/blog_demos
内容:所有原创文章分类汇总及配套源码,波及Java、Docker、Kubernetes、DevOPS等;
《disruptor笔记》系列链接
- 疾速入门
- Disruptor类剖析
- 环形队列的根底操作(不必Disruptor类)
- 事件生产知识点小结
- 事件生产实战
- 常见场景
- 期待策略
- 知识点补充(终篇)
本篇概览
- 通过前文的实战,咱们对Disruptor有了初步意识,借助com.lmax.disruptor.dsl.Disruptor类能够轻松实现以下操作:
- 环形队列初始化
- 指定事件消费者
- 启动消费者线程
- 接下来要面对两个问题:
- 深刻理解Disruptor类是如何实现上述操作的;
- 对Disruptor类有了足够理解时,尝试不必Disruptor,本人入手操作环形队列,实现音讯的生产和生产,这样做的目标是加深对Disruptor外部的意识,做到知其所以然;
- 接下来咱们先解决第一个问题吧,联合Disruptor对象的源码来看看上述三个操作到底做了什么;
环形队列初始化
- 环形队列初始化产生在实例化Disruptor对象的时候,即Disruptor的构造方法:
public Disruptor(final EventFactory<T> eventFactory, final int ringBufferSize, final ThreadFactory threadFactory) { this(RingBuffer.createMultiProducer(eventFactory, ringBufferSize), new BasicExecutor(threadFactory)); }
- <font color="blue">RingBuffer.createMultiProducer</font>办法外部实例化了RingBuffer,如下图红框:
- 记下<font color="red">第一个重要知识点</font>:创立RingBuffer对象;
指定事件消费者
- 在前文中,上面这行代码指定了事件由StringEventHandler生产:
disruptor.handleEventsWith(new StringEventHandler(eventCountPrinter));
- 查看handleEventsWith办法的外部:
public final EventHandlerGroup<T> handleEventsWith(final EventHandler<? super T>... handlers){ return createEventProcessors(new Sequence[0], handlers);}
- 开展createEventProcessors办法,如下图,请重点关注创立SequenceBarrier和BatchEventProcessor等操作:
- 开展上图红框四中的updateGatingSequencesForNextInChain办法,如下图,红框中的ringBuffer.addGatingSequences须要重点关注:
- 小结一下,disruptor.handleEventsWith办法波及到<font color="red">四个重要知识点</font>:
- 创立SequenceBarrier对象,用于接管ringBuffer中的可生产事件
- 创立BatchEventProcessor,负责生产事件
- 绑定BatchEventProcessor对象的异样解决类
- 调用ringBuffer.addGatingSequences,将消费者的Sequence传给ringBuffer
启动消费者线程
- 前文已通过日志确定了生产事件的逻辑是在一个独立的线程中执行的,启动消费者线程的代码如下:
disruptor.start();
- 开展start办法,如下可见,要害代码是<font color="blue">consumerInfo.start(executor)</font>:
public RingBuffer<T> start() { checkOnlyStartedOnce(); for (final ConsumerInfo consumerInfo : consumerRepository) { consumerInfo.start(executor); } return ringBuffer; }
- ConsumerInfo是接口,对应的实现类有EventProcessorInfo和WorkerPoolInfo两种,这里应该是哪种呢?既然起源是consumerRepository,这就要看当初是怎么存入consumerRepository的,后面在剖析createEventProcessors办法时,下图红框中的consumerRepository.add被忽略了,当初须要进去看看:
- 进去后高深莫测,可见ConsumerInfo的实现是EventProcessorInfo:
- 所以,回到后面对<font color="blue">consumerInfo.start(executor)</font>办法的剖析,这里要看的就是EventProcessorInfo的start办法了,如下图,非常简单,就是启动一个线程执行eventprocessor(这个eventprocessor是BatchEventProcessor对象):
- 小结一下,disruptor.start办法波及到<font color="red">一个重要知识点</font>:
- 启动独立线程,用来执行生产事件的业务逻辑;
生产事件的逻辑
- 为了了解音讯解决逻辑,还要重点关注BatchEventProcessor.processEvents办法,如下图所示,其实也很简略,就是不停的从环形队列取出可用的事件,而后再更新本人的Sequence,相当于标记曾经生产到哪里了:
总结
最初总结Disruptor类的重要性能:
- 创立环形队列(RingBuffer对象)
- 创立SequenceBarrier对象,用于接管ringBuffer中的可生产事件
- 创立BatchEventProcessor,负责生产事件
- 绑定BatchEventProcessor对象的异样解决类
- 调用ringBuffer.addGatingSequences,将消费者的Sequence传给ringBuffer
- 启动独立线程,用来执行生产事件的业务逻辑
- 聪慧的您肯定会发现,本文并没有全面剖析Disruptor类的源码,例如after、shutdown等办法都没有提到,的确如此,欣宸在此给您赔罪了,本篇的重点是找出那些与基本功能无关代码,为前面的实战提供理论指导(不必Disruptor类实现音讯生产生产的实战),因而很多高级性能都跳过了;
了解官网流程图
- 此时再看官网流程图,聪慧的您应该很快就能了解此图表白的意思:每个消费者都有本人的Sequence,通过此Sequence获得本人在环形队列中生产的地位,再通过SequenceBarrier来期待可用事件的呈现,等到事件呈现了就用get办法取出具体的事件,给EventHandler来解决:
后续预报
- 此时,咱们对Disruptor类曾经有了比拟深刻的了解,接下来的文章,咱们会尝试不必Disruptor类,仅凭着对RingBuffer对象的操作来实现以下三种性能:
- 100个事件,单个消费者生产;
- 100个事件,三个消费者,每个都单独生产这个100个事件;
- 100个事件,三个消费者独特生产这个100个事件;
你不孤独,欣宸原创一路相伴
- Java系列
- Spring系列
- Docker系列
- kubernetes系列
- 数据库+中间件系列
- DevOps系列
欢送关注公众号:程序员欣宸
微信搜寻「程序员欣宸」,我是欣宸,期待与您一起畅游Java世界...
https://github.com/zq2599/blog_demos