Backend Development 11 min read

Introduction to Disruptor: A High‑Performance Java Message Queue with Full Example

This article introduces the open‑source Disruptor library, explains its core concepts such as Ring Buffer, Sequence, Sequencer and Wait Strategy, and provides a step‑by‑step Java demo—including Maven dependency, event model, handlers, configuration, producer, and test code—to show how to build a fast in‑memory message queue.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
Introduction to Disruptor: A High‑Performance Java Message Queue with Full Example

Disruptor Overview

Disruptor is an open‑source Java framework originally developed by LMAX Exchange to achieve ultra‑low latency and high throughput in producer‑consumer scenarios. It replaces traditional blocking queues with a lock‑free ring buffer, enabling millions of operations per second.

Core Concepts

1. Ring Buffer

A circular buffer that stores events; since version 3.0 it only handles storage and update of data.

2. Sequence

Monotonically increasing numbers that identify each event and track consumer progress, avoiding false sharing.

3. Sequencer

The central component with implementations for single‑producer and multi‑producer modes, providing the concurrency algorithm.

4. Sequence Barrier

Ensures consumers see only published events and coordinates dependencies between consumers.

5. Wait Strategy

Defines how a consumer waits for the next event; multiple strategies exist for different performance trade‑offs.

6. Event

The data object exchanged between producer and consumer; its type is defined by the user.

7. EventProcessor

Holds a consumer’s sequence and runs the event‑handling loop.

8. EventHandler

User‑implemented interface that processes each event.

9. Producer

Any code that publishes events to the Disruptor; no specific interface is required.

Demo Example (8 Steps)

1. Add Maven dependency:

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

2. Define the message model:

@Data
public class MessageModel {
    private String message;
}

3. Implement EventFactory :

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

4. Create an EventHandler (consumer):

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

5. Provide a bean manager to obtain Spring beans:

@Component
public class BeanManager implements ApplicationContextAware {
    private static ApplicationContext applicationContext = null;
    @Override
    public void setApplicationContext(ApplicationContext ctx) throws BeansException {
        applicationContext = ctx;
    }
    public static ApplicationContext getApplicationContext() { return applicationContext; }
    public static Object getBean(String name) { return applicationContext.getBean(name); }
    public static
T getBean(Class
clazz) { return applicationContext.getBean(clazz); }
}

6. Configure the Disruptor and expose a RingBuffer bean:

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

7. Define the producer service interface and implementation:

public interface DisruptorMqService {
    void sayHelloMq(String message);
}

@Slf4j
@Component
@Service
public class DisruptorMqServiceImpl implements DisruptorMqService {
    @Autowired
    private RingBuffer
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("Add message to queue: {}", event);
        } catch (Exception e) {
            log.error("failed to add event", e);
        } finally {
            messageModelRingBuffer.publish(sequence);
        }
    }
}

8. Write a SpringBoot test to publish a message and observe the consumer logs:

@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 consumer
    }
}

Test Output

The logs show the producer recording the message, the event being added to the ring buffer, and the consumer processing it asynchronously with start and end markers.

Conclusion

The producer‑consumer pattern is common, but Disruptor implements it entirely in memory without locks, which explains its exceptional performance for high‑throughput scenarios.

Javabackend developmentconcurrencyMessage QueueDisruptorhigh performance
Code Ape Tech Column
Written by

Code Ape Tech Column

Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn

0 followers
Reader feedback

How this landed with the community

login 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.