原文地址:http://mechanitis.blogspot.com/2011/06/dissecting-disruptor-how-do-i-read-from.html 作者是 Trisha Gee, LMAX 公司的一位女工程师。
这是理解 LMAX 开发的 Disruptor 模式 系列博客的下一篇。
从 上一篇博客 我们都明白了什么是 Ring Buffer 以及 它有多棒。遗憾的是,我还没有提到当你实际使用 Disruptor 时,怎样读写数据。
ConsumerBarrier 与消费者
这里我要稍微反过来介绍,因为总的来说这一段比较容易理解。假设一些魔法已经把数据填入 Ring Buffer 了,怎样从 Ring Buffer 读出这些数据?
(唔,我开始后悔使用 Paint/Gimp 了。尽管这是个购买绘图板的好借口,如果我继续写下去的话... UML 界的权威们大概也在诅咒我的名字了。)
消费者(Consumer)是一个想从 Ring Buffer 里拿出数据的线程,它可以访问 ConsumerBarrier 对象——这个对象由 RingBuffer 创建并且代表消费者与它互动。就像 Ring Buffer 显然需要序号才能找到下一个可用节点一样,消费者一样需要知道序号——每个消费者都需要找到下一个它要访问的序号。在上面的例子中,消费者处理完了 Ring Buffer 里序号 8 之前的所有数据,那么它期待访问的下一个序号是 9。
消费者可以调用 ConsumerBarrier 对象的 waitFor() 方法,传递它需要的下一个序号:
final long availableSeq = consumerBarrier.waitFor(nextSequence);
ConsumerBarrier 返回 RingBuffer 的最大可访问序号——在上面的例子中是 12。ConsumerBarrier 持有一个 WaitStrategy 值来决定它如何等待这个序号,我现在暂时不会描述它的细节,代码里已经概括了每一种 WaitStrategy 的优点和缺点 。
接下来怎么做?
接下来,消费者会一直逛来逛去,等待更多数据被写入 Ring Buffer。并且,写入数据后消费者会收到通知——节点 9,10,11 和 12 已写入。现在序号 12 到了,消费者可以指示 ConsumerBarrier 去拿这些序号里的数据了。
拿到了数据后,消费者会更新自己的游标 (cursor)。
你应该已经感觉得到,这样做是怎样有助于抹平延迟曲线尖峰了——代替逐个逐个节点的询问“我能拿下一个数据吗?现在怎么样了?现在呢?”,消费者 Consumer 只需要简单的说“当你拿到的数字比这个要大的时候请告诉我”,函数返回值会告诉它有多少个新的数据节点可以读取。因为这些新的节点的确已经写入(Ring Buffer 本身的序号已经更新),而且消费者对这些节点的唯一操作是读而不是写,因此访问不用加锁。这样简直太好了,不仅代码可以更加安全和简单,而且不用加锁的速度超快。
另一个额外的好处是——你可以用多个消费者 Consumer 读同一个 RingBuffer, 不需要加锁,也不需要用另外的队列来协调不同的线程。这样你可以在 Disruptor 的协调下实现真正的并发数据处理。
BatchConsumer 是一个消费端的例子代码。如果你实现了 BatchHandler, 你可以用 BatchConsumer 来完成上面我提到的复杂工作。它很容易实现需要成批处理节点(例如上文 9-12 的节点)的功能而不用单独读取每一个节点。
更新:注意 Disruptor 2.0 版使用了与本文不一样的命名。如果你对类名感到困惑,请阅读我的 变更总结。
相关推荐
disruptor笔记之四:事件消费知识点小结(csdn)————程序
赠送jar包:disruptor-3.3.0.jar; 赠送原API文档:disruptor-3.3.0-javadoc.jar; 赠送源代码:disruptor-3.3.0-sources.jar; 赠送Maven依赖信息文件:disruptor-3.3.0.pom; 包含翻译后的API文档:disruptor-...
赠送jar包:disruptor-3.3.7.jar 赠送原API文档:disruptor-3.3.7-javadoc.jar 赠送源代码:disruptor-3.3.7-sources.jar 包含翻译后的API文档:disruptor-3.3.7-javadoc-API文档-中文(简体)-英语-对照版.zip ...
赠送jar包:disruptor-3.3.0.jar; 赠送原API文档:disruptor-3.3.0-javadoc.jar; 赠送源代码:disruptor-3.3.0-sources.jar; 赠送Maven依赖信息文件:disruptor-3.3.0.pom; 包含翻译后的API文档:disruptor-...
SourceAnalysis_Disruptor Disruptor原始码解析
卡夫卡消费者的破坏者演示如何在Kafka 0.9 Consumer上使用LMAX Disruptor 好处->一旦先前的使用者完全处理完消息,便可以使用序列屏障来提交消息。想象力是极限。如果环形缓冲区可以容纳在L3缓存中,则处理速度会更...
Disruptor3.x Disruptor使用方式 EventHandler[] eventHandlers=new DisruptorEventHandler[]{new DisruptorEventHandler()}; DisruptorPublisher dp=new DisruptorPublisher(1024, eventHandlers); dp.start(); ...
Conversant ConcurrentQueue、Disruptor BlockingQueue 和 ConcurrentStack Disruptor是Java中性能最高的线程内传输机制。 Conversant Disruptor 是这种环形缓冲区中性能最高的实现,因为它几乎没有开销,并且采用了...
Error: java.lang.NoSuchMethodError: com.lmax.disruptor.dsl.Disruptor.<init>(Lcom/lmax/disruptor/EventFactory;ILjava/util/concurrent/ThreadFactory;Lcom/lmax/disruptor/dsl/ProducerType;Lcom/lmax/...
Disruptor-cpp 总览 Disruptor-cpp是功能齐全的C ++端口。 实现java Disruptor v3.3.7中可用的所有功能。 建造 编译器 Clang 3.8或更高版本 GCC 5.0或更高版本 Microsoft Visual C ++ 2015或更高版本 Linux 必须在...
赠送jar包:disruptor-3.3.7.jar; 赠送原API文档:disruptor-3.3.7-javadoc.jar; 赠送源代码:disruptor-3.3.7-sources.jar; 赠送Maven依赖信息文件:disruptor-3.3.7.pom; 包含翻译后的API文档:disruptor-...
Java工具:高性能并发工具Disruptor简单使用
disruptor-3.4.4.jar 官方github下载 亲测可用,大家赶紧下载吧 后续再补充其他常用jar(但不好下载的)
从功能上来看,Disruptor 是实现了“队列”的功能,而且是一个有界队列。那么它的应用场景自然就是“生产者-消费者”模型的应用场合了。 可以拿 JDK 的 BlockingQueue 做一个简单对比,以便更好地认识 Disruptor 是...
简单讲解disruptor并附上demo
Disruptor是一个开源的Java框架,它被设计用于在生产者—消费者(producer-consumer problem,简称PCP)问题上获得尽量高的吞吐量(TPS)和尽量低的延迟。Disruptor是LMAX在线交易平台的关键组成部分,LMAX平台使用...
Disruptor 是一个 Java 的并发编程框架,大大的简化了并发程序开发的难度,在性能上也比 Java 本身提供的一些并发包要好。 标签:Disruptor
disruptor:高性能Java线程间通讯库
212,598 ops/secRun 1, Disruptor=51,921,079 ops/secRun 2, Disruptor=50,864,699 ops/secRun 3, Disruptor=59,630,292 ops/secRun 4, Disruptor=62,227,753 ops/secRun 5, Disruptor=59,988,002 ops/secRun 6, ...
disruptor 缓冲队列 高效