慎入,有点乱,只是学习记录,disruptor_2.10.4
1、Disruptor对象有一个EventProcessorRepository对象
2、EventProcessorRepository里储存的是EventProcessorInfo和EventHandler(既创建Disruptor对象时设置的EventHandler)的映射关系,
及EventProcessorInfo和EventProcessor(实际为BatchEventProcessor)的映射关系
2.1 首先看看BatchEventProcessor是什么东西
BatchEventProcessor继承自EventProcessor,是一个消费者的执行体,说白了就是一个线程,可以看到它的run方法。
它主要有三个成员RingBuffer、SequenceBarrier和EventHandler,这里还需要看看这个SequenceBarrier是什么东西。
barrier在Disruptor的createEventProcessors()中创建的
SequenceBarrier barrier = ringBuffer.newBarrier(Util.getSequencesFor(barrierEventProcessors));
可以在RingBuffer(Sequencer)中看到barrier实际是ProcessingSequenceBarrier对象
new ProcessingSequenceBarrier(waitStrategy, cursor, sequencesToTrack);
先看看它储存了一些什么信息:
waitStrategy:消费者的等待策略
cursor:这个保存的是RingBuffer 环中当前的序号
sequencesToTrack:Sequence[] dependentSequences先理解为依赖的序列号,具体干嘛的还要待看
2.2 现在开看看生产者和消费者是如何运作的
现从Disruptor.start()开始
找到EventProcessorRepository中最后面的EventProcessor
EventProcessor[] gatingProcessors = eventProcessorRepository.getLastEventProcessorsInChain();
从EventProcessor中找到最后面的Sequence,然后设置ringBuffer最后面消费者对应的Sequence
ringBuffer.setGatingSequences(Util.getSequencesFor(gatingProcessors));
接着执行executor,运行EventProcessor(线程)
executor.execute(eventProcessorInfo.getEventProcessor());
2.3 现在看看EventProcessor(消费者线程)都干了些什么
首先它要获取可用的Sequence是哪个
final long availableSequence = sequenceBarrier.waitFor(nextSequence);
走到BlockingWaitStrategy.waitFor()
现得到ringbuffer中当前消费者所在的availableSequence = cursor.get()位置,比较请求的位置和当前的位置,如果请求的位置比当前的位置大,说明消费者已经没有可消费的事件了。执行processorNotifyCondition.await();等待
2.4 看看生产者又是怎么处理的
生产者先要获取下一个sequence是多少,调用ringBuffer.next();
走到MultithreadedClaimStrategy.incrementAndGet(gatingSequences);
这个gatingSequences就是生产者的依赖Sequence,他就是2.2中ringBuffer最后面消费者对应的Sequences,从中找出最小的并保存,先取出最后生产者的sequence并加1,如果sequence+1大于最小消费者sequence。则挂起线程LockSupport.parkNanos(1L);
否则返回可生产的sequence。
3 关于Sequence
可以看到RingBuffer(既Sequencer)有一个Sequence cursor成员
同时AbstractMultithreadedClaimStrategy有一个Sequence claimSequence成员
BatchEventProcessor里也由一个Sequence
这两个Sequence有什么关联了sequence
首先claimSequence保存的是请求的sequence,里面保存的是当前被请求的最大的序号。
生产者先拿到claimSequence中保存的最大序号的下一个序号。
接着,拿到从请求的序号执行ringbuffer.publish()。
3.1生产者分配数据
claimStrategy.serialisePublishing(sequence, cursor,batchSize);
先计算资源(环)中预期的最大序号expectedSequence
然后依次更新ringbuffer的cursor,保存需要请求的所有序号中最大的(如果有多个sequence请求)
3.2 通知消费者
waitStrategy.signalAllWhenBlocking();
现在唯一的疑问就是消费者是如何知道生产者生产到哪个位置了的?
看到BatchEventProcessor.run()中的如下代码,通过SequenceBarrier对象获取当前生产者的位置
final long availableSequence = sequenceBarrier.waitFor(nextSequence);
原来是根据这个sequenceBarrier中的Sequence cursorSequence;中的值来判断当前生产者的位置的。
Sequence cursorSequence这个是在sequenceBarrier也就是ProcessingSequenceBarrier构造时,传入的ringbuffer的Sequence cursor。
sequenceBarrier是如何从cursorSequence获取的当前生产者的位置的了?
联想到另外一个问题,看到BatchEventProcessor是没有WaitStrategy成员对象。那WaitStrategy在消费者这头是在哪里用到的了。
BatchEventProcessor调用ProcessingSequenceBarrier.waitFor()
ProcessingSequenceBarrier又调用waitStrategy.waitFor(),现在看看BlockingWaitStrategy.waitFor()都做了些什么?
如何消费者的请求序号大于ringbuffer的当前序号,则执行processorNotifyCondition.await();挂起线程
否则返回请求的序号,给消费者使用
- [Flask]学习杂记--模板
这个学习杂记主要不是分享经验,更多是记录下falsk的体验过程,以后做东西在深入研究,因为django之前用的时间比较长,所以很多概念都是一看而过,做个试验了解下flask的功能. flask中使用是 ...
- Java编程思想学习杂记(1-4章)
程序流程控制 移位运算符 移位运算符面向的运算对象是二进制的位,可单独用它们处理整数类型.左移位运算符(<<)能将运算符左边的运算对象向左移动运算符右侧指定的位数(在低位补0)." ...
- Thinking in Java学习杂记(5-6章)
Java中可以通过访问控制符来控制访问权限.其中包含的类别有:public, "有好的"(无关键字), protected 以及 private.在C++中,访问指示符控制着它后面 ...
- Thinking in Java学习杂记(第7章)
将一个方法调用同一个方法主体连接到一起就称为"绑定"(Binding).若在程序运行以前执行绑定,就叫做"早期绑定".而Java中绑定的所有方法都采用后期绑定技 ...
- Disruptor学习笔记
前言 以前一直听说有Disruptor这个东西,都说性能很强大,所以这几天自己也看了一下. 下面是自己的学习笔记,另外推荐几篇自己看到写的比较好的博客: Disruptor——一种可替代有界队列完成并 ...
- Android学习杂记
Jni接口学习资料: http://www.cnblogs.com/lsnproj/archive/2012/01/09/2317519.html classLoader和插件化: http://bl ...
- django 学习杂记
django1.9 学习路径 http://python.usyiyi.cn/django/intro/tutorial02.html django 中url路径带参数,在view中应该如何处理 应该 ...
- 无锁并发框架Disruptor学习入门
刚刚听说disruptor,大概理一下,只为方便自己理解,文末是一些自己认为比较好的博文,如果有需要的同学可以参考. 本文目标:快速了解Disruptor是什么,主要概念,怎么用 1.Disrupto ...
- Disruptor学习笔记(一):基本原理和概念
一.Disruptor基本原理 在多线程开发中,我们常常遇到这样一种场景:一些线程接受用户请求,另外一些线程处理这些请求.比如日志处理中的日志输入和告警.这种典型的生产者消费者场景十分常见,而生产者消 ...
随机推荐
- BZOJ3751 NOIP2014 解方程(Hash)
题目链接 BZOJ3751 这道题的关键就是选取取模的质数. 我选了4个大概几万的质数,这样刚好不会T 然后统计答案的时候如果对于当前质数,产生了一个解. 那么对于那些对这个质数取模结果为这个数的数 ...
- jenkins按版本发布maven项目
1.先为java这个项目创建三个版本 vim pom.xml vim src/main/java/com/ghz/testweb/App.java git add . git commit -m &q ...
- 再次了解android中屏幕尺寸,单位等
android设备多种多样,要让你的app能够适配所有的屏幕是一件很痛苦的事情,在做适配之前我们首先需要了解android中dimension的定义 android中dimension是如何定义的? ...
- Ubuntu 16.04常用软件清单
软件:(链接: https://pan.baidu.com/s/1jIgTJhk 密码: qxg3) 配套安装教程:http://www.cnblogs.com/EasonJim/tag/ubuntu ...
- Wdatepick控件只能选当前时间以前的时间
WdatePicker限制只能选当天,只能选以前的时间 (1)WdatePicker限制只能选以前的时间(不能选当天): onfocus="WdatePicker({startDate:'% ...
- 迅雷在P2P网络中的另类上传速度
如上图,我们一般在下载BT时,一般P2P是边下载边上传. 但是迅雷在自己的软件中可以设置上传速度,反而在展示时却把P2P协议的速度不在上传那么显示,而是使用协议速度来进行展示:并且这个速度无法设置. ...
- javascript 对象初探 (四)--- 内建对象之旅之Boolean
var a = new Boolean() 我们要明白一点在这里的b是一个对象而不是一个基本数据类型的布尔值.如果想将b转化成基本数据类型的布尔值,我们可以调用她的valueof()方法(继承自Obj ...
- 用Redis存储Tomcat集群的Session(转载)
本文转自http://blog.csdn.net/chszs/article/details/42610365 感谢作者 前段时间,我花了不少时间来寻求一种方法,把新开发的代码推送到到生产系统中部署, ...
- -[__NSCFString longValue]: unrecognized selector sent to instance
You can use NSString methods intValue longLongValue. 这个使用longvalue会crash报上面的错误
- 邁向IT專家成功之路的三十則鐵律 鐵律二十五:IT人屈辱之道-十倍奉還
現代人普遍火氣都很大,與人爭論時只要有一點點感到屈辱,便會開始大聲反擊,甚至於暴力相向.至於企業中的人事相鬥,則是典型的來個明爭暗鬥,直到成為老闆眼中的紅人,在逐漸掌握了權力之後再來個內部大清洗,不久 ...