Disruptor的消费者实现是WorkerProcessor类,都实现了EventProcessor接口,这个接口继承了Runnable接口,因此,每个消费者实则就是一条线程,具体的业务逻辑都实现自run()方法,一群不重复消费的并行消费者集合被称为一个WorkerPool。
private final Sequence workSequence = new Sequence(Sequencer.INITIAL_CURSOR_VALUE);
在一个WorkerPool中,该消费者集合的消费进度通过workSequence来进行共享。
for (int i = 0; i < numWorkers; i++)
{
workProcessors[i] = new WorkProcessor<>(
ringBuffer,
sequenceBarrier,
workHandlers[i],
exceptionHandler,
workSequence);
}
在WorkerPool的构造方法中,将会依次构造消费者实例到其数组中等待执行,具体的消费者线程启动在disruptor的start()方法被调用的时候,这里的sequenceBarrier用来控制消费者的消费进度,在消费者没有消息消费的时候根据的等待策略执行相应的操作。
那么具体的消费者具体逻辑在WorkerProcessor的run()方法。
核心逻辑在run()的一段循环中。
while (true)
{
try
{
// if previous sequence was processed - fetch the next sequence and set
// that we have successfully processed the previous sequence
// typically, this will be true
// this prevents the sequence getting too far forward if an exception
// is thrown from the WorkHandler
if (processedSequence)
{
processedSequence = false;
do
{
nextSequence = workSequence.get() + 1L;
sequence.set(nextSequence - 1L);
}
while (!workSequence.compareAndSet(nextSequence - 1L, nextSequence));
}
if (cachedAvailableSequence >= nextSequence)
{
event = ringBuffer.get(nextSequence);
workHandler.onEvent(event);
processedSequence = true;
}
else
{
cachedAvailableSequence = sequenceBarrier.waitFor(nextSequence);
}
}
消费者线程在启动的时候,首先会从workSequence中尝试通过cas得到当前消费进度的下一个序列号,在这里通过cas在整个WorkerPool中每条线程都能得到自己当前唯一的消费序列号。
在完成消费序列号的获取后,将会通过等待策略的waitFor()方法等待,直到当前Disruptor的环形队列中的消息序列号到达从workSequence获取到的WorkerPool中唯一的序列号为止,以BlockingWaitingStrategy为例子,每次生产者生产消息之后都会唤醒一次等待的线程,将会判断当前的消息序列号是否小于当前消费者线程的所持序列号,如果是,则继续等待,否则开始根据当前唤醒时的消息序列号来从环形队列中获取消息进行消费。消费之后,继续通过cas得到下一个唯一的序列号,循环上述的方式等待执行下一个消息。