Disruptor是一个高性能的并发队列,三个特性保障了它的高效性:
1. CAS乐观锁:
利用CAS(compare and swap) 乐观锁代替了重量级的lock锁, 提升了性能。
2. 消除伪共享
伪共享是计算机的CPU缓存导致的。现在的计算机的CPU缓存一般是以行的形式来保存,一行大概是64个字节。java中一个Long是8个字节,所以一行能存8个Long。但是这里就有一个问题了,假设一个缓存行里存了多个数据,而其中一个是经常变动的,就会导致整个缓存行失效,其他的数据就无法高效率的被应用。
Disruptor利用了padding来解决这个问题,上代码:
class LhsPadding
{
protected long p1, p2, p3, p4, p5, p6, p7;
}
class Value extends LhsPadding
{
protected volatile long value;
}
class RhsPadding extends Value
{
protected long p9, p10, p11, p12, p13, p14, p15;
}
Disruptor的Sequence继承了RhsPadding, 一个有效数据的前7,后7都是无效填充值。这就保证了这个有效数据一定是独立的占据了一个缓存行。
3. RingBuffer数据结构
RingBuffer是一个环形数组。其size是2的N次方,取余并不是使用%运算,都是使用的&与运算。
当然其不仅解决了数组快速访问的问题,也解决了不需要再次分配内存的问题,减少了垃圾回收,因为我们0,10,20等都是执行的同一片内存区域,这样就不需要再次分配内存,频繁的被JVM垃圾回收器回收。
Disruptor的使用:
几个重要的参数:
- ThreadFactory:线程工厂,用于我们Disruptor中生产者消费的时候需要的线程。
- EventFactory:事件工厂,用于产生我们队列元素的工厂,在Disruptor中,他会在初始化的时候直接填充满RingBuffer,一次到位。
- EventHandler:用于处理Event的handler,多个消费者独立消费,互不影响,
- WorkHandler: 用于处理Event的handler,多个消费者都是共享同一个队列。
- WaitStrategy:等待策略