Boost Java Performance with Disruptor: A Hands‑On Guide to High‑Throughput Queues

This article introduces the high‑performance Java library Disruptor, explains its core concepts such as Ring Buffer, Sequence, and Wait Strategy, and provides a step‑by‑step demo with Maven configuration, code examples, and test results to help developers implement fast, lock‑free producer‑consumer queues.

Java High-Performance Architecture
Java High-Performance Architecture
Java High-Performance Architecture
Boost Java Performance with Disruptor: A Hands‑On Guide to High‑Throughput Queues

1. Introduction to Disruptor

Disruptor is a high‑performance queue developed by the UK forex trading firm LMAX to solve latency problems of in‑memory queues, achieving throughput comparable to I/O operations.

Based on Disruptor, a single‑threaded system can sustain 6 million orders per second; after a 2010 QCon talk it attracted industry attention.

It is an open‑source Java framework designed for the producer‑consumer problem, aiming for maximum throughput (TPS) and minimal latency.

From a functional perspective, Disruptor implements a bounded queue, making it suitable for any producer‑consumer scenario. LMAX uses it to process up to 6 million TPS, and it can bring significant performance gains to other domains as well.

Disruptor is more a design pattern than a traditional framework, offering a way to dramatically improve performance for programs involving concurrency, buffering, producer‑consumer models, or transaction processing.

GitHub: https://github.com/LMAX-Exchange/disruptor

2. Core Concepts of Disruptor

Understanding the following domain objects helps grasp how Disruptor works.

Ring Buffer

As its name suggests, a circular buffer. Since version 3.0 its responsibility is reduced to storing and updating events; users can replace it with custom implementations for advanced scenarios.

Sequence

Sequences assign monotonically increasing numbers to events, tracking processing progress and preventing false sharing between CPU caches.

Note: preventing false sharing is one of the key reasons for Disruptor’s high performance.

Sequencer

The Sequencer interface has two implementations—SingleProducerSequencer and MultiProducerSequencer—that define the concurrent algorithm for passing data between producers and consumers.

Sequence Barrier

Maintains references to the main published sequence of the RingBuffer and to dependent consumer sequences, determining whether a consumer can process more events.

Wait Strategy

Defines how a consumer waits for the next event; Disruptor provides several strategies with different performance characteristics for various scenarios.

Event

In Disruptor terminology, an Event is the data exchanged between producer and consumer, defined by the user.

EventProcessor

Holds a specific consumer’s sequence and provides the event loop that invokes the event‑handling implementation.

EventHandler

User‑implemented interface that processes events; it is the actual consumer logic.

Producer

Any code that publishes events to the Disruptor; the framework does not define a specific interface for it.

3. Demo – Step‑by‑Step Implementation

Add Maven dependency

<dependency>
    <groupId>com.lmax</groupId>
    <artifactId>disruptor</artifactId>
    <version>3.4.4</version>
</dependency>

Message model

/**
 * Message body
 */
@Data
public class MessageModel {
    private String message;
}

EventFactory implementation

public class HelloEventFactory implements EventFactory<MessageModel> {
    @Override
    public MessageModel newInstance() {
        return new MessageModel();
    }
}

EventHandler (consumer)

@Slf4j
public class HelloEventHandler implements EventHandler<MessageModel> {
    @Override
    public void onEvent(MessageModel event, long sequence, boolean endOfBatch) {
        try {
            // Simulate async processing delay
            Thread.sleep(1000);
            log.info("Consumer starts processing");
            if (event != null) {
                log.info("Consumed message: {}", event);
            }
        } catch (Exception e) {
            log.info("Consumer processing failed");
        }
        log.info("Consumer ends processing");
    }
}

BeanManager to obtain Spring beans

/**
 * Retrieve instantiated beans
 */
@Component
public class BeanManager implements ApplicationContextAware {

    private static ApplicationContext applicationContext = null;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        BeanManager.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext() { return applicationContext; }
    public static Object getBean(String name) { return applicationContext.getBean(name); }
    public static <T> T getBean(Class<T> clazz) { return applicationContext.getBean(clazz); }
}

MQManager configuration

@Configuration
public class MQManager {

    @Bean("messageModel")
    public RingBuffer<MessageModel> messageModelRingBuffer() {
        ExecutorService executor = Executors.newFixedThreadPool(2);
        HelloEventFactory factory = new HelloEventFactory();
        int bufferSize = 1024 * 256; // must be power of two
        Disruptor<MessageModel> disruptor = new Disruptor<>(factory, bufferSize, executor,
                ProducerType.SINGLE, new BlockingWaitStrategy());
        disruptor.handleEventsWith(new HelloEventHandler());
        disruptor.start();
        return disruptor.getRingBuffer();
    }
}

Service interface and implementation (producer)

public interface DisruptorMqService {
    /**
     * Send a message
     */
    void sayHelloMq(String message);
}

@Slf4j
@Component
@Service
public class DisruptorMqServiceImpl implements DisruptorMqService {

    @Autowired
    private RingBuffer<MessageModel> messageModelRingBuffer;

    @Override
    public void sayHelloMq(String message) {
        log.info("record the message: {}", message);
        long sequence = messageModelRingBuffer.next();
        try {
            MessageModel event = messageModelRingBuffer.get(sequence);
            event.setMessage(message);
            log.info("Added message to queue: {}", event);
        } catch (Exception e) {
            log.error("failed to add event to ring buffer", e);
        } finally {
            messageModelRingBuffer.publish(sequence);
        }
    }
}

Test class

@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(classes = DemoApplication.class)
public class DemoApplicationTests {

    @Autowired
    private DisruptorMqService disruptorMqService;

    @Test
    public void sayHelloMqTest() throws Exception {
        disruptorMqService.sayHelloMq("Message arrived, Hello world!");
        log.info("Message queue sent");
        Thread.sleep(2000); // wait for async processing
    }
}

Test output

2023-04-05 14:31:18.543  INFO 7274 --- [main] c.e.u.d.d.s.Impl.DisruptorMqServiceImpl : record the message: 消息到了,Hello world!
2023-04-05 14:31:18.545  INFO 7274 --- [main] c.e.u.d.d.s.Impl.DisruptorMqServiceImpl : Added message to queue: MessageModel(message=消息到了,Hello world!)
2023-04-05 14:31:18.545  INFO 7274 --- [main] c.e.utils.demo.DemoApplicationTests : Message queue sent
2023-04-05 14:31:19.547  INFO 7274 --- [pool-1-thread-1] c.e.u.d.disrupMq.mq.HelloEventHandler : Consumer starts processing
2023-04-05 14:31:19.547  INFO 7274 --- [pool-1-thread-1] c.e.u.d.disrupMq.mq.HelloEventHandler : Consumed message: MessageModel(message=消息到了,Hello world!)
2023-04-05 14:31:19.547  INFO 7274 --- [pool-1-thread-1] c.e.u.d.disrupMq.mq.HelloEventHandler : Consumer ends processing

4. Summary

The producer‑consumer pattern is common, and many message‑queue solutions can achieve similar results. Disruptor distinguishes itself by implementing the queue entirely in memory without locks, which is the primary reason for its exceptional efficiency.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaconcurrencyMessage QueueDisruptorhigh performanceProducer Consumer
Java High-Performance Architecture
Written by

Java High-Performance Architecture

Sharing Java development articles and resources, including SSM architecture and the Spring ecosystem (Spring Boot, Spring Cloud, MyBatis, Dubbo, Docker), Zookeeper, Redis, architecture design, microservices, message queues, Git, etc.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.