这种模式提供了很好的批处理行为,可以使用这种批处理代码来实现EventHandler,在disruptor里性能测试FizzBuzzEventHandler就是一个很好的例子,。
处理系统组件之间的依赖关系
Disruptor处理系统内部多组件的依赖关系,而不引入任何线程竞争的做法很有意思。Disruptor遵循的是单线程写入,多线程读取的做法。disruptor的原始设计是支持几步具有特定顺序的串行流水线操作 - 这种操作在企业级的系统里很常见。图8演了一个标准的三步流水线操作:
图8首先,所有事件都会写入硬盘(日志“Journaling”操作),以便容灾恢复。第二所有事件会备份(Replication操作)到第二台服务器上,只有这些步骤都完成之后系统才能处理实际的业务操作(Business Logic)。
串行做这三步操作是一个合理的做法,但不是最有效率的。日志和备份操作可以并行,因为它们相互独立。但业务操作不行,因为它依赖前两者,图9演示了这个依赖关系。

如果使用disruptor,前两步(日志和备份)可以直接读RingBuffer。跟图7示意的,它们都使用一个屏障(Sequence Barrier)来得到RingBuffer下一个可读取的序列号。它们各自维护自己的序列号,这样方便它们自己知道已经读到哪了,并使用BatchEventProcessor来处理事件(日志和备份)。
业务线程也会从同一个RingBuffer里读取事件,不过只能处理前两个线程处理完的事件。这个限制通过第二个SequenceBarrier来实现,它被配置来读取日志线程和备份线程的序列号,返回它们的最小值,以告诉业务线程安全读取的范围。
只有每一个EventProcessor都使用序列号屏障(Sequence Barrier)来确定可以安全处理的事件范围,才能从RingBuffer里读取数据。如图10。

虽然有很多线程读取不同的序利号,但由于都是简单递增自己内部的序利号,所以线程间没有竞争。
多个生产线程
disruptor也支持,但是本文没有说如何支持,放在后面写。
结论
虽然disruptor的原理已经比较熟悉了,但是其API还不是很了解,我写了一个实验性的代码,来完善我的理解 - 不过随着理解的深入,代码会不断更新:
https://github.com/shiyimin/12306ngpm/blob/8be9178d318618f905aaed45fa6025df09371c31/trunk/tpms/src/test/java/org/ng12306/tpms/disruptorConceptProofTest.java
posted @
以上就是关于disruptor的全部内容,相信你一定会非常满意。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-14095-2.html
文笔悟性临摹性值得称道
有童年有梦想有希望也需要坚持