首先这里说的队列也仅限于Java内部的消息队列队列有界性锁结构队列类型ArrayBlockingQueue有界加锁数组阻塞LinkedBlockingQueue可选加锁链表阻塞ConcurrentLinkedQueue无界无锁链表非阻塞LinkedTransferQueue无界无锁链表阻塞PriorityBlockingQueue无界加锁堆阻塞DelayQueue无界加锁堆阻塞1.3.2 Disruptor应用场景
参考使用到disruptor的一些框架.1.3.2.1 log4j2
先从了解 Disruptor 的核心概念开始,来了解它是如何运作的。下面介绍的概念模型,既是领域对象,也是映射到代码实现上的核心对象。1.4.1 Ring Buffer
Disruptor中的数据结构,用于存储生产者生产的数据 如其名,环形的缓冲区。曾经 RingBuffer 是 Disruptor 中的最主要的对象,但从3.0版本开始,其职责被简化为仅仅负责对通过 Disruptor 进行交换的数据(事件)进行存储和更新。在一些更高级的应用场景中,Ring Buffer 可以由用户的自定义实现来完全替代。
序号,在Disruptor框架中,任何地方都有序号 生产者生产的数据放在RingBuffer中的哪个位置,消费者应该消费哪个位置的数据,RingBuffer中的某个位置的数据是什么,这些都是由这个序号来决定的。这个序号可以简单的理解为一个AtomicLong类型的变量。其使用了padding的方法去消除缓存的伪共享问题。
序号生成器,这个类主要是用来协调生产者的 在生产者生产数据的时候,Sequencer会产生一个可用的序号(Sequence),然后生产者就就知道数据放在环形队列的那个位置了。
序号屏障 我们都知道,消费者在消费数据的时候,需要知道消费哪个位置的数据。消费者总不能自己想取哪个数据消费,就取哪个数据消费吧。这个SequencerBarrier起到的就是这样一个“栅栏”般的阻隔作用。你消费者想消费数据,得,我告诉你一个序号(Sequence),你去消费那个位置上的数据。要是没有数据,就好好等着吧
Wait Strategy决定了一个消费者怎么等待生产者将事件(Event)放入Disruptor中。 设想一种这样的情景:生产者生产的非常慢,而消费者消费的非常快。那么必然会出现数据不够的情况,这个时候消费者怎么进行等待呢?WaitStrategy就是为了解决问题而诞生的。
我们使用一个简单的例子来体验一下Disruptor,生产者会传递一个long类型的值到消费者,消费者接受到这个值后会打印出这个值。2.1 添加依赖
Disruptor 的 API 十分简单,主要有以下几个步骤2.2.1 定义事件
首先创建一个 LongEvent 类,这个类将会被放入环形队列中作为消息内容。
事件(Event)就是通过 Disruptor 进行交换的数据类型。
为了使用Disruptor的内存预分配event,我们需要定义一个EventFactory 事件工厂(Event Factory)定义了如何实例化前面第1步中定义的事件(Event),需要实现接口 com.lmax.disruptor.EventFactory。
为了让消费者处理这些事件,所以我们这里定义一个事件处理器,负责打印event
通过实现接口 com.lmax.disruptor.EventHandler 定义事件处理的具体实现。
Disruptor 定义了 com.lmax.disruptor.WaitStrategy 接口用于抽象 Consumer 如何等待新事件,这是策略模式的应用
注意ringBufferSize的大小必须是2的N次方
在Disruptor的3.0版本中,由于加入了丰富的Lambda风格的API,可以用来帮组开发人员简化流程。所以在3.0版本后首选使用Event Publisher/Event Translator来发布事件。
消费者-生产者启动类,其依靠构造Disruptor对象,调用start()方法完成启动线程。Disruptor 需要ringbuffer环,消费者数据处理工厂,WaitStrategy等
测试结果
Event: value = 为消费者接收到的数据,sequence为数据在ringbuffer环的位置。
本文由传智教育博学谷教研团队发布。
如果本文对您有帮助,欢迎关注和点赞;如果您有任何建议也可留言评论或私信,您的支持是我坚持创作的动力。
转载请注明出处!
欢迎光临 IT评测·应用市场-qidao123.com技术社区 (https://dis.qidao123.com/) | Powered by Discuz! X3.4 |