Original address: http://www.symphonious.net/2011/07/11/lmax-disruptor-high-performance-low-latency-and-simple-too/
The LMAX disruptor is an ultra-high performance, low-latency message exchange between threads. It's a bit like a queue on steroids (but quite a lot of steroids) and are one of the key innovations used to make the LMAX Exchange run so fast. There is a rapidly growing set of information on what the disruptor are, why it's important and how it works–a good pl Aces to start are the list of articles and for the on-going stuff, follow LMAX Blogs. For really detailed stuff, there's also the White Paper (PDF).
While the disruptor pattern was ultimately very simple to work with, setting up multiple consumers with the dependencies be Tween them can require a bit too much boilerplate code for my liking. To make it quick and easy for 99% of cases, I ' ve whipped-a simple DSL for the disruptor pattern. For example, to wire up a "diamond pattern" of consumers:
(Image blatantly stolen from Trisha Gee ' s excellent series explaining the disruptor pattern)
In this scenario, consumers C1 and C2 can process entries as soon as the producer (P1) puts them on the ring buffer (in PA Rallel). However, consumer C3 have to wait for bothC1 and C2 to complete before it processes the entries. In real life this might is because we need to both journal the data to disk (C1) and validate the data (C2) before we do t He actual business logic (C3).
With the raw disruptor syntax, these consumers would is created with the following code:
Executor Executor = Executors.newcachedthreadpool (); Batchhandler handler1 = new MyBatchHandler1 (); Batchhandler handler2 = new MyBatchHandler2 (); Batchhandler Handler3 = new MyBatchHandler3 () ringbuffer ringbuffer = new Ringbuffer (entry_factory, ring_buffer_size); Consumerbarrier consumerBarrier1 = Ringbuffer.createconsumerbarrier (); Batchconsumer consumer1 = new Batchconsumer (ConsumerBarrier1, handler1); Batchconsumer consumer2 = new Batchconsumer (ConsumerBarrier1, Handler2); Consumerbarrier consumerBarrier2 =ringbuffer.createconsumerbarrier (Consumer1, Consumer2); Batchconsumer Consumer3 = new Batchconsumer (ConsumerBarrier2, Handler3); Executor.execute (Consumer1); Executor.execute (Consumer2); Executor.execute (CONSUMER3); Producerbarrier producerbarrier =ringbuffer.createproducerbarrier (CONSUMER3);
We have to create our actual handlers (the instances of Mybatchhandler), plus consumer barriers, Batchconsumer Instanc Es and actually execute the consumers on their own threads. The DSL can handle pretty much all of this setup work for us with the end result being:
Executor Executor = Executors.newcachedthreadpool (); Batchhandler handler1 = new MyBatchHandler1 (); Batchhandler handler2 = new MyBatchHandler2 (); Batchhandler Handler3 = new MyBatchHandler3 ();D isruptorwizard DW = new Disruptorwizard (entry_factory, Ring_buffer_size, Executor);d W.consumewith (Handler1, Handler2). then (HANDLER3); Producerbarrier producerbarrier = Dw.createproducerbarrier ();
We can even build parallel chains of consumers in a diamond pattern:
(Thanks to Trish for using she fancy graphics tablet to create a decent version of this image instead of my original Finge R painting on an IPad ...)
Dw.consumewith (Handler1a, HANDLER2A);d w.after (HANDLER1A). Consumewith (HANDLER1B);d w.after (HANDLER2A). ConsumeWith (HANDLER2B);d w.after (HANDLER1B, HANDLER2B). Consumewith (Handler3); Producerbarrier producerbarrier = Dw.createproducerbarrier ();
The DSL is quite new so any feedback on it would being greatly appreciated and of course feel free to fork it on GitHub and I Mprove it.
LMAX Disruptor–high performance, low Latency and simple Too reprint