Package com.lmax.disruptor
The Disruptor is a concurrent programming framework for exchanging and coordinating work as a continuous series of events. It can be used as an alternative to wiring processing stages together via queues. The Disruptor design has the characteristics of generating significantly less garbage than queues and separates the concurrency concerns so non-locking algorithms can be employed resulting in greater scalability and performance.
It works on the principle of having a number of stages that are each single threaded with local state and memory. No global memory exists and all communication is achieved by passing messages/state via managed ring buffers.
Almost any graph or pipeline structure can be composed via one or more Disruptor patterns.
UniCast a series of items between 1 publisher and 1 EventProcessor.
track to prevent wrap +------------------+ | | | v +----+ +-----+ +----+ +====+ +====+ +-----+ | P1 |--->| EP1 | | P1 |--->| RB |<---| SB | | EP1 | +----+ +-----+ +----+ +====+ +====+ +-----+ claim get ^ | | | +--------+ waitFor
Sequence a series of messages from multiple publishers
track to prevent wrap +--------------------+ | | | v +----+ +----+ +====+ +====+ +-----+ | P1 |-------+ | P1 |--->| RB |<---| SB | | EP1 | +----+ | +----+ +====+ +====+ +-----+ v ^ get ^ | +----+ +-----+ +----+ | | | | P2 |--->| EP1 | | P2 |------+ +---------+ +----+ +-----+ +----+ | waitFor ^ | +----+ | +----+ | | P3 |-------+ | P3 |------+ +----+ +----+
Pipeline a series of messages
+----+ +-----+ +-----+ +-----+ | P1 |--->| EP1 |--->| EP2 |--->| EP3 | +----+ +-----+ +-----+ +-----+ track to prevent wrap +----------------------------------------------------------------+ | | | v +----+ +====+ +=====+ +-----+ +=====+ +-----+ +=====+ +-----+ | P1 |--->| RB | | SB1 |<---| EP1 |<---| SB2 |<---| EP2 |<---| SB3 |<---| EP3 | +----+ +====+ +=====+ +-----+ +=====+ +-----+ +=====+ +-----+ claim ^ get | waitFor | waitFor | waitFor | | | | +---------+---------------------+---------------------+
Multicast a series of messages to multiple EventProcessors
+-----+ track to prevent wrap +----->| EP1 | +--------------------+----------+----------+ | +-----+ | | | | | | v v v +----+ +-----+ +----+ +====+ +====+ +-----+ +-----+ +-----+ | P1 |--->| EP2 | | P1 |--->| RB |<---| SB | | EP1 | | EP2 | | EP3 | +----+ +-----+ +----+ +====+ +====+ +-----+ +-----+ +-----+ | claim get ^ | | | | +-----+ | | | | +----->| EP3 | +---------+----------+----------+ +-----+ waitFor
Replicate a message then fold back the results
+-----+ track to prevent wrap +----->| EP1 |-----+ +-------------------------------+ | +-----+ | | | | v | v +----+ +-----+ +----+ +====+ +=====+ +-----+ | P1 | | EP3 | | P1 |--->| RB |<--------------| SB2 |<---| EP3 | +----+ +-----+ +----+ +====+ +=====+ +-----+ | ^ claim ^ get | waitFor | +-----+ | | | +----->| EP2 |-----+ +=====+ +-----+ | +-----+ | SB1 |<---| EP1 |<-----+ +=====+ +-----+ | ^ | | +-----+ | +-------| EP2 |<-----+ waitFor +-----+
Code Example
// Event holder for data to be exchanged public final class ValueEvent { private long value; public long getValue() { return value; } public void setValue(final long value) { this.value = value; } public final static EventFactory<ValueEvent> EVENT_FACTORY = new EventFactory<ValueEvent>() { public ValueEvent newInstance() { return new ValueEvent(); } }; } // Callback handler which can be implemented by EventProcessors final EventHandler<ValueEvent> eventHandler = new EventHandler<ValueEvent>() { public void onEvent(final ValueEvent event, final long sequence, final boolean endOfBatch) throws Exception { // process a new event as it becomes available. } }; RingBuffer<ValueEvent> ringBuffer = new RingBuffer<ValueEvent>(ValueEvent.EVENT_FACTORY, new SingleThreadedClaimStrategy(BUFFER_SIZE), new SleepingWaitStrategy()); SequenceBarrier<ValueEvent> sequenceBarrier = ringBuffer.newBarrier(); BatchEventProcessor<ValueEvent> batchProcessor = new BatchEventProcessor<ValueEvent>(sequenceBarrier, eventHandler); ringBuffer.setGatingSequences(batchProcessor.getSequence()); // Each processor runs on a separate thread EXECUTOR.submit(batchProcessor); // Publishers claim events in sequence long sequence = ringBuffer.next(); ValueEvent event = ringBuffer.get(sequence); event.setValue(1234); // publish the event so it is available to EventProcessors ringBuffer.publish(sequence);
-
Interface Summary Interface Description BatchStartAware Cursored Implementors of this interface must provide a single long value that represents their current cursor value.DataProvider<T> EventFactory<T> Called by theRingBuffer
to pre-populate all the events to fill the RingBuffer.EventHandler<T> Callback interface to be implemented for processing events as they become available in theRingBuffer
EventPoller.Handler<T> EventProcessor An EventProcessor needs to be an implementation of a runnable that will poll for events from theRingBuffer
using the appropriate wait strategy.EventReleaseAware EventReleaser EventSequencer<T> EventSink<E> EventTranslator<T> Implementations translate (write) data representations into events claimed from theRingBuffer
.EventTranslatorOneArg<T,A> Implementations translate another data representations into events claimed from theRingBuffer
EventTranslatorThreeArg<T,A,B,C> Implementations translate another data representations into events claimed from theRingBuffer
EventTranslatorTwoArg<T,A,B> Implementations translate another data representations into events claimed from theRingBuffer
EventTranslatorVararg<T> Implementations translate another data representations into events claimed from theRingBuffer
ExceptionHandler<T> Callback handler for uncaught exceptions in the event processing cycle of theBatchEventProcessor
LifecycleAware Implement this interface in yourEventHandler
to be notified when a thread for theBatchEventProcessor
starts and shuts down.SequenceBarrier Coordination barrier for tracking the cursor for publishers and sequence of dependentEventProcessor
s for processing a data structureSequenced Sequencer Coordinates claiming sequences for access to a data structure while tracking dependentSequence
sSequenceReportingEventHandler<T> Used by theBatchEventProcessor
to set a callback allowing theEventHandler
to notify when it has finished consuming an event if this happens after theEventHandler.onEvent(Object, long, boolean)
call.TimeoutHandler WaitStrategy Strategy employed for makingEventProcessor
s wait on a cursorSequence
.WorkHandler<T> Callback interface to be implemented for processing units of work as they become available in theRingBuffer
. -
Class Summary Class Description AbstractSequencer Base class for the various sequencer types (single/multi).AggregateEventHandler<T> An aggregate collection ofEventHandler
s that get called in sequence for each event.BatchEventProcessor<T> Convenience class for handling the batching semantics of consuming entries from aRingBuffer
and delegating the available events to anEventHandler
.BlockingWaitStrategy Blocking strategy that uses a lock and condition variable forEventProcessor
s waiting on a barrier.BusySpinWaitStrategy Busy Spin strategy that uses a busy spin loop forEventProcessor
s waiting on a barrier.EventPoller<T> Experimental poll-based interface for the Disruptor.ExceptionHandlers Provides static methods for accessing a defaultExceptionHandler
object.ExceptionHandlers.DefaultExceptionHandlerHolder FatalExceptionHandler Convenience implementation of an exception handler that using standard JDK logging to log the exception asLevel
.SEVERE and re-throw it wrapped in aRuntimeException
FixedSequenceGroup Hides a group of Sequences behind a single SequenceIgnoreExceptionHandler Convenience implementation of an exception handler that using standard JDK logging to log the exception asLevel
.INFOLhsPadding LiteBlockingWaitStrategy Variation of theBlockingWaitStrategy
that attempts to elide conditional wake-ups when the lock is uncontended.LiteTimeoutBlockingWaitStrategy Variation of theTimeoutBlockingWaitStrategy
that attempts to elide conditional wake-ups when the lock is uncontended.MultiProducerSequencer Coordinator for claiming sequences for access to a data structure while tracking dependentSequence
s.NoOpEventProcessor No operation version of aEventProcessor
that simply tracks aSequence
.NoOpEventProcessor.SequencerFollowingSequence Sequence that follows (by wrapping) another sequencePhasedBackoffWaitStrategy Phased wait strategy for waitingEventProcessor
s on a barrier.ProcessingSequenceBarrier SequenceBarrier
handed out for gatingEventProcessor
s on a cursor sequence and optional dependentEventProcessor
(s), using the given WaitStrategy.RhsPadding RingBuffer<E> Ring based store of reusable entries containing the data representing an event being exchanged between event producer andEventProcessor
s.RingBufferFields<E> RingBufferPad Sequence Concurrent sequence class used for tracking the progress of the ring buffer and event processors.SequenceGroup SequenceGroups Provides static methods for managing aSequenceGroup
object.SingleProducerSequencer Coordinator for claiming sequences for access to a data structure while tracking dependentSequence
s.SingleProducerSequencerFields SingleProducerSequencerPad SleepingWaitStrategy Sleeping strategy that initially spins, then uses a Thread.yield(), and eventually sleep (LockSupport.parkNanos(n)
) for the minimum number of nanos the OS and JVM will allow while theEventProcessor
s are waiting on a barrier.TimeoutBlockingWaitStrategy Value WorkerPool<T> WorkerPool contains a pool ofWorkProcessor
s that will consume sequences so jobs can be farmed out across a pool of workers.WorkProcessor<T> AWorkProcessor
wraps a singleWorkHandler
, effectively consuming the sequence and ensuring appropriate barriers.YieldingWaitStrategy Yielding strategy that uses a Thread.yield() forEventProcessor
s waiting on a barrier after an initially spinning. -
Enum Summary Enum Description EventPoller.PollState -
Exception Summary Exception Description AlertException Used to alertEventProcessor
s waiting at aSequenceBarrier
of status changes.InsufficientCapacityException Exception thrown when it is not possible to insert a value into the ring buffer without it wrapping the consuming sequences.TimeoutException