慎入,有点乱,只是学习记录,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();挂起线程
        否则返回请求的序号,给消费者使用

Disruptor学习杂记的更多相关文章

  1. [Flask]学习杂记--模板

    这个学习杂记主要不是分享经验,更多是记录下falsk的体验过程,以后做东西在深入研究,因为django之前用的时间比较长,所以很多概念都是一看而过,做个试验了解下flask的功能. flask中使用是 ...

  2. Java编程思想学习杂记(1-4章)

    程序流程控制 移位运算符 移位运算符面向的运算对象是二进制的位,可单独用它们处理整数类型.左移位运算符(<<)能将运算符左边的运算对象向左移动运算符右侧指定的位数(在低位补0)." ...

  3. Thinking in Java学习杂记(5-6章)

    Java中可以通过访问控制符来控制访问权限.其中包含的类别有:public, "有好的"(无关键字), protected 以及 private.在C++中,访问指示符控制着它后面 ...

  4. Thinking in Java学习杂记(第7章)

    将一个方法调用同一个方法主体连接到一起就称为"绑定"(Binding).若在程序运行以前执行绑定,就叫做"早期绑定".而Java中绑定的所有方法都采用后期绑定技 ...

  5. Disruptor学习笔记

    前言 以前一直听说有Disruptor这个东西,都说性能很强大,所以这几天自己也看了一下. 下面是自己的学习笔记,另外推荐几篇自己看到写的比较好的博客: Disruptor——一种可替代有界队列完成并 ...

  6. Android学习杂记

    Jni接口学习资料: http://www.cnblogs.com/lsnproj/archive/2012/01/09/2317519.html classLoader和插件化: http://bl ...

  7. django 学习杂记

    django1.9 学习路径 http://python.usyiyi.cn/django/intro/tutorial02.html django 中url路径带参数,在view中应该如何处理 应该 ...

  8. 无锁并发框架Disruptor学习入门

    刚刚听说disruptor,大概理一下,只为方便自己理解,文末是一些自己认为比较好的博文,如果有需要的同学可以参考. 本文目标:快速了解Disruptor是什么,主要概念,怎么用 1.Disrupto ...

  9. Disruptor学习笔记(一):基本原理和概念

    一.Disruptor基本原理 在多线程开发中,我们常常遇到这样一种场景:一些线程接受用户请求,另外一些线程处理这些请求.比如日志处理中的日志输入和告警.这种典型的生产者消费者场景十分常见,而生产者消 ...

随机推荐

  1. HOJ - 2715最小费用流

    国庆八天乐,刷题也快乐. HOJ崩了,但是VJ可以把题目挂出来. 题目链接:https://vjudge.net/contest/188441#problem/A 涉及到矩阵里面的网络流,化为图来做. ...

  2. ML | spectral clustering

    What's xxx In multivariate statistics and the clustering of data, spectral clustering techniques mak ...

  3. android应用无法接收到广播?

    本篇文章记录Android应用无法接收到广播的几种case 1. 没有register 广播其实是一种订阅者模式,所以当然需要先register,register的方式有两种 1.1  through ...

  4. Ural 1774 Barber of the Army of Mages 最大流

    题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1774 1774. Barber of the Army of Mages Time li ...

  5. eclipse 五种断点

    1. Line BreakpointLine Breakpoin是最简单的Eclipse断点,只要双击某行代码对应的左侧栏,就对该行设置上断点. 2. WatchpointLine Breakpoin ...

  6. Spring Boot中使用AOP记录请求日志

    这周看别人写的springboot后端代码中有使用AOP记录请求日志,以前没接触过,因此学习下. 一.AOP简介 AOP为Aspect Oriented Programming的缩写,意为:面向切面编 ...

  7. Spring配置项之<aop:aspectj-autoproxy />

    通过配置织入@Aspectj切面 虽然可以通过编程的方式织入切面,但是一般情况下,我们还是使用spring的配置自动完成创建代理织入切面的工作. 通过aop命名空间的<aop:aspectj-a ...

  8. ApplicationContext介绍

    如果说BeanFactory是Spring的心脏,那么ApplicationContext就是完整的身躯了.ApplicationContext由BeanFactory派生而来,提供了更多面向实际应用 ...

  9. 高性能内存池NedAlloc

    http://www.nedprod.com/programs/portable/nedmalloc/ http://blog.sina.com.cn/s/blog_6f5b220601012x4t. ...

  10. filter和spring 的interceptor都是单例的,都不是线程安全的

    Filter 是在 Servlet 容器启动时就初始化的,因此可以认为是以单例对象存在的,如果一个请求线程对其中的成员变量修改的话,会影响到其他的请求线程,因此认为是多线程不安全的.