Disruptor的核心是解决伪共享,通过给填充整个缓存行来达到提高缓存命中率以及提高并发。通过一个环状数据结构实现RingBuffer。主要使用的方式如下,一个存储数据的RingBuffer,一个执行消费的线程生成器。
public Disruptor(final EventFactory<T> eventFactory, final int ringBufferSize, final ThreadFactory threadFactory)
{
this(RingBuffer.createMultiProducer(eventFactory, ringBufferSize), new BasicExecutor(threadFactory));
}
创建支持多生产者的对应大小的RingBuffer,以及需要存储的初始对象EventFactory,初始化消费端常用的等待策略BlockingWaitStrategy,当然还有其他几种策略可以配置。
public static <E> RingBuffer<E> createMultiProducer(EventFactory<E> factory, int bufferSize)
{
return createMultiProducer(factory, bufferSize, new BlockingWaitStrategy());
}
public static <E> RingBuffer<E> createMultiProducer(
EventFactory<E> factory,
int bufferSize,
WaitStrategy waitStrategy)
{
MultiProducerSequencer sequencer = new MultiProducerSequencer(bufferSize, waitStrategy);
return new RingBuffer<E>(factory, sequencer);
}
初始化提供者的定序器,bufferSize大小必须是2的幂次方,这样在获取环状位置时就可以直接使用位运算替代取余。availableBuffer这个数组是保存对应的RingBuffer数组的对象是否可用的标志,与真实的存储数据是一一对应的。
public MultiProducerSequencer(int bufferSize, final WaitStrategy waitStrategy)
{
super(bufferSize, waitStrategy);
availableBuffer = new int[bufferSize];
indexMask = bufferSize - 1;
indexShift = Util.log2(bufferSize);
initialiseAvailableBuffer();
}
public AbstractSequencer(int bufferSize, WaitStrategy waitStrategy)
{
if (bufferSize < 1)
{
throw new IllegalArgumentException("bufferSize must not be less than 1");
}
if (Integer.bitCount(bufferSize) != 1)
{
throw new IllegalArgumentException("bufferSize must be a power of 2");
}
this.bufferSize = bufferSize;
this.waitStrategy = waitStrategy;
}
给标志位数组设置不可用初始值,SCALE = UNSAFE.arrayIndexScale(int[].class)为数组元素的占位大小,BASE = UNSAFE.arrayBaseOffset(int[].class)代表该数组所在的偏移量