news 2026/10/15 17:11:32

面试官:你的项目哪里用到了 Disruptor?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
面试官:你的项目哪里用到了 Disruptor?

Disruptor 是一个开源的高性能内存队列,由英国外汇交易公司 LMAX 开发的,获得了 2011 年的 Oracle 官方的 Duke's Choice Awards(Duke 选择大奖)。

Disruptor 提供的功能类似于 Kafka 、RocketMQ 这类分布式队列,不过,其作为范围是 JVM(内存)。

Disruptor 解决了 JDK 内置线程安全队列的性能和内存安全问题。

JDK 中常见的线程安全的队列如下:

队列名字锁是否有界
ArrayBlockingQueue加锁(ReentrantLock)有界
LinkedBlockingQueue加锁(ReentrantLock)有界
LinkedTransferQueue无锁(CAS)无界
ConcurrentLinkedQueue无锁(CAS)无界

从上表中可以看出:这些队列要不就是加锁有界,要不就是无锁无界。而加锁的的队列势必会影响性能,无界的队列又存在内存溢出的风险。

因此,一般情况下,我们都是不建议使用 JDK 内置线程安全队列。

Disruptor 就不一样了!它在无锁的情况下还能保证队列有界,并且还是线程安全的。

1.广播场景

广播场景在我们的开发工作中并不少见,比如系统收到上游系统的一个请求消息,然后把这个消息发送给多个下游系统来处理。Disruptor 支持广播模式。比如消费者生产的消息由三个消费者来消费:

public class Broadcast { public static void main(String[] args) throws InterruptedException { int bufferSize = 1024; Disruptor<LongEvent> disruptor = new Disruptor<>(LongEvent::new, bufferSize, DaemonThreadFactory.INSTANCE); EventHandler<LongEvent> consumer1 = new LongEventHandler("consumer1"); EventHandler<LongEvent> consumer2 = new LongEventHandler("consumer2"); EventHandler<LongEvent> consumer3 = new LongEventHandler("consumer3"); disruptor.handleEventsWith(consumer1, consumer2, consumer3); disruptor.start(); RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer(); ByteBuffer bb = ByteBuffer.allocate(8); for (long l = 0; true; l++) { bb.putLong(0, l); ringBuffer.publishEvent((event, sequence, buffer) -> event.set(buffer.getLong(0)), bb); Thread.sleep(1000); } } }

2.日志收集

再来看一个日志收集的例子。这里我们假设一个场景,业务系统集群有 3 个节点,每个节点打印的业务日志发送到 Disruptor,Disruptor 下游有 3 个消费者负责日志收集。

这里我们需要重新定义一个日志收集处理类,代码如下:

public class LogCollectHandler implements WorkHandler<LongEvent> { public LogCollectHandler(String consumer) { this.consumer = consumer; } private String consumer; @Override public void onEvent(LongEvent event) { System.out.println("consumer: " + consumer + ",Event: " + event); } }

下面这个代码是绑定消费者的代码:

public static void main(String[] args) throws InterruptedException { int bufferSize = 1024; Disruptor<LongEvent> disruptor = new Disruptor<>(LongEvent::new, bufferSize, DaemonThreadFactory.INSTANCE); WorkHandler<LongEvent> consumer1 = new LogCollectHandler("consumer1"); WorkHandler<LongEvent> consumer2 = new LogCollectHandler("consumer2"); WorkHandler<LongEvent> consumer3 = new LogCollectHandler("consumer3"); disruptor.handleEventsWithWorkerPool(consumer1, consumer2, consumer3); disruptor.start(); }

需要注意的是,上面使用的是 Disruptor 的handleEventsWithWorkerPool方法,使用的消费者不是EventHandler,而是WorkHandler。消费者组里面的消费者如果是WorkHandler,那消费者之间就是有竞争的,比如一个 Event 已经被 consumer1 消费过,那就不再会被其他消费者消费了。消费者组里面的消费者如果是EventHandler,那消费者之间是没有竞争的,所有消息都会消费。

3.责任链

责任链这种设计模式我们都比较熟悉了,同一个对象的处理有多个不同的逻辑,每个逻辑作为一个节点组成责任链,比如收到一条告警消息,处理节点分为:给开发人员发送邮件、给运维人员发送短信、给业务人员发送 OA 消息。

Disruptor 支持链式处理消息,看下面的示例代码:

public static void main(String[] args) throws InterruptedException { int bufferSize = 1024; Disruptor<LongEvent> disruptor = new Disruptor<>(LongEvent::new, bufferSize, DaemonThreadFactory.INSTANCE); EventHandler<LongEvent> consumer1 = new LongEventHandler("consumer1"); EventHandler<LongEvent> consumer2 = new LongEventHandler("consumer2"); EventHandler<LongEvent> consumer3 = new LongEventHandler("consumer3"); disruptor.handleEventsWith(consumer1).then(consumer2).then(consumer3); disruptor.start(); }

Disruptor 也支持多个并行责任链,下图是 2 条责任链的场景:

图片

这里给出一个示例代码:

public static void main(String[] args) throws InterruptedException { int bufferSize = 1024; Disruptor<LongEvent> disruptor = new Disruptor<>(LongEvent::new, bufferSize, DaemonThreadFactory.INSTANCE); EventHandler<LongEvent> consumer1 = new LongEventHandler("consumer1"); EventHandler<LongEvent> consumer2 = new LongEventHandler("consumer2"); EventHandler<LongEvent> consumer3 = new LongEventHandler("consumer3"); EventHandler<LongEvent> consumer4 = new LongEventHandler("consumer4"); EventHandler<LongEvent> consumer5 = new LongEventHandler("consumer5"); EventHandler<LongEvent> consumer6 = new LongEventHandler("consumer6"); disruptor.handleEventsWith(consumer1).then(consumer2).then(consumer3); disruptor.handleEventsWith(consumer4).then(consumer5).then(consumer6); disruptor.start(); }

4.多任务协作

一个经典的例子,我们在泡咖啡之前,需要烧水、洗被子、磨咖啡粉,这三个步骤可以并行,但是需要等着三步都完成之后,才可以泡咖啡。

当然,这个例子可以用 Java 中的 CompletableFuture 来实现,代码如下:

public static void main(String[] args){ ExecutorService executor = ...; CompletableFuture future1 = CompletableFuture.runAsync(() -> { try { washCup(); } catch (InterruptedException e) { e.printStackTrace(); } }, executor); CompletableFuture future2 = CompletableFuture.runAsync(() -> { try { hotWater(); } catch (InterruptedException e) { e.printStackTrace(); } }, executor); CompletableFuture future3 = CompletableFuture.runAsync(() -> { try { grindCoffee(); } catch (InterruptedException e) { e.printStackTrace(); } }, executor); CompletableFuture.allOf(future1, future2, future3).thenAccept( r -> { System.out.println("泡咖啡"); } ); System.out.println("我是主线程"); }

同样,使用 Disruptor 也可以实现这个场景,看下面代码:

public static void main(String[] args) throws InterruptedException { int bufferSize = 1024; Disruptor<LongEvent> disruptor = new Disruptor<>(LongEvent::new, bufferSize, DaemonThreadFactory.INSTANCE); EventHandler<LongEvent> consumer1 = new LongEventHandler("consumer1"); EventHandler<LongEvent> consumer2 = new LongEventHandler("consumer2"); EventHandler<LongEvent> consumer3 = new LongEventHandler("consumer3"); EventHandler<LongEvent> consumer4 = new LongEventHandler("consumer4"); disruptor.handleEventsWith(consumer1, consumer2, consumer3).then(consumer4); disruptor.start(); }

5.多消费者组

类比主流消息队列的场景,Disruptor 也可以实现多消费者组的场景,组间并行消费互不影响,组内消费者竞争消息,如下图:

示例代码如下:

public static void main(String[] args) throws InterruptedException { int bufferSize = 1024; Disruptor<LongEvent> disruptor = new Disruptor<>(LongEvent::new, bufferSize, DaemonThreadFactory.INSTANCE); WorkHandler<LongEvent> consumer1 = new LogWorkHandler("consumer1"); WorkHandler<LongEvent> consumer2 = new LogWorkHandler("consumer2"); WorkHandler<LongEvent> consumer3 = new LogWorkHandler("consumer3"); WorkHandler<LongEvent> consumer4 = new LogWorkHandler("consumer4"); WorkHandler<LongEvent> consumer5 = new LogWorkHandler("consumer5"); WorkHandler<LongEvent> consumer6 = new LogWorkHandler("consumer6"); disruptor.handleEventsWithWorkerPool(consumer1, consumer2, consumer3); disruptor.handleEventsWithWorkerPool(consumer4, consumer5, consumer6); disruptor.start(); }

6.总结

通过消费者的灵活组合,Disruptor 的使用场景非常丰富。本文介绍了 Disruptor 的 5 个典型使用场景。在选型的时候,除了使用场景,更多地要考虑到 Disruptor 作为高性能内存队列的这个特点。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 22:27:47

AI人工智能如何正确入行(小白程序员必收藏)

到底做什么&#xff0c;才算真正入行AI&#xff1f; 这个话题我在之前的分享中多次提及&#xff0c;今天结合工业界实际场景再系统梳理一遍&#xff1a;在企业中直接落地AI技术的岗位&#xff0c;核心可分为三大类——算法类、工程类、数据类。 当下网络上&#xff0c;无论是…

作者头像 李华
网站建设 2026/10/16 1:19:18

深入浅出 CAS:从 CPU 指令到 Java 17 原子类实战

这篇文章会用 Java 17 的视角&#xff0c;把 CAS 从底层原理到实际落地系统地讲清楚。 目标只有一个&#xff1a;看完这一篇&#xff0c;你对 CAS 的理解不再停留在“有三个参数 V/E/N”这种记忆层面&#xff0c;而是能从 CPU 指令一路推演到 Java 代码&#xff0c;再对框架源…

作者头像 李华
网站建设 2026/10/15 16:14:42

Thinkphp和Laravel基于Web的课程设计选题管理系统

目录ThinkPHP与Laravel框架的课程设计选题管理系统摘要项目开发技术介绍PHP核心代码部分展示系统结论源码获取/同行可拿货,招校园代理ThinkPHP与Laravel框架的课程设计选题管理系统摘要 基于ThinkPHP的选题管理系统 ThinkPHP作为国内流行的PHP框架&#xff0c;适合快速开发中小…

作者头像 李华
网站建设 2026/10/15 17:00:01

【收藏不迷路】大模型学习进阶篇:避开误区,从实战到落地全攻略

随着大模型技术的普及&#xff0c;越来越多程序员和AI小白投身其中&#xff0c;但不少人陷入“学了就忘”“实战卡壳”“落地无门”的困境。相较于基础入门&#xff0c;掌握科学的学习方法、精准避开技术坑点、聚焦场景落地&#xff0c;才是快速吃透大模型的关键。本文基于实战…

作者头像 李华
网站建设 2026/10/16 2:18:44

飞机起落架减震系统

1.2飞机起落架的布置形式 起落架的布置形式是指飞机起落架支柱(支点)的数目和其相对于飞机重心的布置特点。目前&#xff0c;飞机上通常采用四种起落架形式&#xff1a; 图1.1 后三点式起落架 后三点式起落架&#xff1a;这种起落架有一个尾支柱和两个主起落架。并且飞机的重…

作者头像 李华
网站建设 2026/10/13 12:03:41

普通人想入网络安全,到底该走哪条路?

对普通人来说&#xff0c;网络安全这条路到底该怎么走&#xff1f; 由于我之前写了不少网络安全技术相关的故事文章&#xff0c;不少读者朋友知道我是从事网络安全相关的工作&#xff0c;于是经常有人在微信里问我&#xff1a; 我刚入门网络安全&#xff0c;该怎么学&#xff…

作者头像 李华