深入理解Disruptor - 无锁并发框架的革命

1. Disruptor框架简介

概述: Disruptor是一种高性能的内存队列,最初由LMAX开发,目的是在低延迟交易系统中替代传统的阻塞队列。它通过使用环形数组和无锁的发布/订阅模式,显著降低了线程间通信的延迟。这种设计使得它在多生产者-单消费者的场景中表现出色,尤其是在财务、游戏、日志处理和其他实时系统中。

import com.lmax.disruptor.*;
import com.lmax.disruptor.dsl.Disruptor;
import java.nio.ByteBuffer;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;// 定义事件
class LongEvent {private long value;void set(long value) {this.value = value;}
}// 事件工厂
class LongEventFactory implements EventFactory<LongEvent> {public LongEvent newInstance() {return new LongEvent();}
}// 事件处理器
class LongEventHandler implements EventHandler<LongEvent> {public void onEvent(LongEvent event, long sequence, boolean endOfBatch) {System.out.println("Event: " + event.value);}
}public class DisruptorDemo {public static void main(String[] args) throws Exception {// 配置DisruptorExecutor executor = Executors.newCachedThreadPool();LongEventFactory factory = new LongEventFactory();int bufferSize = 1024;Disruptor<LongEvent> disruptor = new Disruptor<>(factory, bufferSize, executor);// 连接事件处理器disruptor.handleEventsWith(new LongEventHandler());// 启动DisruptorRingBuffer<LongEvent> ringBuffer = disruptor.start();// 发布事件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);}}
}

这段代码展示了如何设置Disruptor,定义事件、事件工厂和事件处理器。它创建了一个环形缓冲区,事件被发布到缓冲区中,并由事件处理器消费。

2. 核心概念与架构

概述: Disruptor的核心是基于环形数组(Ring Buffer)的无锁队列设计。这种设计利用了缓存行和CPU预测加载的优势,减少了不必要的缓存失效,从而实现高性能。环形数组作为一个固定大小的队列,通过循环利用其位置,避免了频繁的内存分配和回收。每个元素的位置是预先确定的,这使得生产者和消费者能够独立地并且几乎无等待地访问数据。此外,Disruptor支持多种消费者模式,包括单消费者和多消费者配置,使其在不同的应用场景中都能提供优异的性能。

import com.lmax.disruptor.RingBuffer;public class RingBufferExample {public static void main(String[] args) {// 创建RingBufferRingBuffer<LongEvent> ringBuffer = RingBuffer.createSingleProducer(new LongEventFactory(), 1024, new YieldingWaitStrategy());// 获取下一个可用序号long sequence = ringBuffer.next();try {// 获取指定序号的元素LongEvent event = ringBuffer.get(sequence);// 填充数据event.set(12345);} finally {// 发布事件ringBuffer.publish(sequence);}}
}

这个示例展示了如何在Ring Buffer中发布一个事件。首先,通过ringBuffer.next()获取下一个可用的序列号,然后在这个位置上设置数据,最后通过ringBuffer.publish()来发布这个事件。

3. Disruptor的关键特性

概述: Disruptor的一大特色是其多样的等待策略,它们对应不同的性能和资源占用特性。例如,BlockingWaitStrategy使用锁和条件变量,适用于CPU资源较少的场况;SleepingWaitStrategy通过睡眠减少CPU占用,适合于低延迟不是首要目标的应用;YieldingWaitStrategy在等待时循环并不断检查依赖的序列号,这种策略在高性能的应用中很有用;而BusySpinWaitStrategy则一直占用CPU,以实现最低的延迟。此外,Disruptor的事件处理器模型允许构建复杂的依赖图,从而实现精细的事件流控制。

import com.lmax.disruptor.dsl.ProducerType;
import com.lmax.disruptor.dsl.Disruptor;// 设置Disruptor
Disruptor<LongEvent> disruptor = new Disruptor<>(new LongEventFactory(),1024,Executors.defaultThreadFactory(),ProducerType.SINGLE,new SleepingWaitStrategy());// 其他配置和启动逻辑...

这段代码演示了如何根据不同的场景选择合适的等待策略来创建Disruptor实例。不同的等待策略会影响整体的性能和资源使用。

4. 高级应用与优化

概述: Disruptor不仅适用于基本的生产者-消费者场景,还能处理更复杂的应用场景,如并发编程中的多生产者和多消费者模式。在高并发环境下,Disruptor的性能优化尤为关键。这包括选择合适的等待策略,优化数据结构以减少伪共享,以及合理分配线程以充分利用多核处理器的优势。例如,在金融交易系统中,通过细粒度地调节Disruptor的配置,可以大幅提高交易处理的速度和效率。

import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.BusySpinWaitStrategy;// 多生产者模式下的Disruptor配置
Disruptor<LongEvent> disruptor = new Disruptor<>(new LongEventFactory(),1024,Executors.defaultThreadFactory(),ProducerType.MULTI,new BusySpinWaitStrategy());// 多消费者配置
EventHandler<LongEvent>[] consumers = new LongEventHandler[4];
for (int i = 0; i < consumers.length; i++) {consumers[i] = new LongEventHandler();
}
disruptor.handleEventsWithWorkerPool(consumers);// 其他配置和启动逻辑...

5. Disruptor的实践指南

概述: 虽然Disruptor提供了高性能的并发处理能力,但正确地设置和使用它是成功实现其潜力的关键。这包括对环境的配置、正确地初始化Disruptor实例、编写事件处理逻辑,以及监控和调试Disruptor应用。一个实用的指南可以帮助开发者避免常见的错误,并在开发过程中做出更加明智的决策。

// 初始化Disruptor
Disruptor<LongEvent> disruptor = new Disruptor<>(new LongEventFactory(),1024,Executors.newSingleThreadExecutor(),ProducerType.SINGLE,new YieldingWaitStrategy());// 定义事件处理器
EventHandler<LongEvent> handler = new LongEventHandler();
disruptor.handleEventsWith(handler);// 启动Disruptor
RingBuffer<LongEvent> ringBuffer = disruptor.start();// 在应用结束时关闭Disruptor
Runtime.getRuntime().addShutdownHook(new Thread(disruptor::shutdown));

这段代码提供了Disruptor应用的基本框架,包括初始化、事件处理配置和优雅地关闭Disruptor实例。

6. Disruptor在现代软件开发中的意义

概述: 在现代软件开发中,尤其是在需要高吞吐量和低延迟的应用中,Disruptor框架扮演着重要角色。它不仅在金融服务领域表现出色,也被广泛应用于游戏开发、大数据处理、实时消息系统等多个领域。Disruptor的设计理念和实现为处理大量实时数据提供了新的可能性,同时也推动了并发编程模型的发展。它的出现促使开发者重新思考如何有效利用多核处理器资源,以及如何在保持高性能的同时降低系统的复杂度。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/217438.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【1day】​万户协同办公平台 iWebPDF/DocumentEdit.jsp文件 SQL注入漏洞学习

注:该文章来自作者日常学习笔记,请勿利用文章内的相关技术从事非法测试,如因此产生的一切不良后果与作者无关。 目录 一、漏洞描述 二、影响版本 三、资产测绘 四、漏洞复现

如何构建和安装Go程序

引言 到目前为止,在我们的[如何在Go中编码]系列中,您已经使用命令[go run]自动编译源代码并运行生成的可执行文件。尽管这个命令对于在命令行中测试你的代码很有用,但发布或部署你的应用程序需要你将代码构建为可共享的二进制可执行文件,或包含可以运行你的应用程序的机器…

LangChain学习二:提示-实战(下半部分)

文章目录 上一节内容&#xff1a;LangChain学习二&#xff1a;提示-实战&#xff08;上半部分&#xff09;学习目标&#xff1a;提示词中的示例选择器和输出解释器学习内容一&#xff1a;示例选择器1.1 LangChain自定义示例选择器1.2 实现自定义示例选择器1.2.1实战&#xff1a…

静态路由的原理和配置

一.路由器的工作原理 首先我们知道路由器是工作在网络层的&#xff0c;那就是三层设备。网络层的功能主要为&#xff1a;不同网段之间通信、最佳路径选择也就是逻辑地址&#xff08;ip地址&#xff09;寻址、转发数据。 1.路由器是什么 路由器是能将数据包转发到正确的目的地…

【QT 5 调试软件+(Linux下验证>>>>串口相关初试串口)+Windows下qt代码在Linux下运行+参考win下历程+基础样例】

【QT 5 调试软件Linux下验证>>>>串口相关初试串口参考win下历程基础样例】 1、前言2、实验环境3、先行了解4、自我总结-win下工程切到Linux下1、平台无关的代码&#xff1a;2、依赖的库&#xff1a;3、文件路径和换行符&#xff1a;4、编译器差异&#xff1a;5、构…

什么是防抖与节流?应用场景举例

防抖节流如何处理防抖与节流 防抖节流防抖例子节流例子Vue Axios全局接口防抖、节流封装实现 小结 防抖 防抖&#xff1a;触发高频事件后n秒内函数只会执行一次&#xff0c;如果n秒内高频事件再次被触发&#xff0c;则重新计算时间 应用场景&#xff1a; 提交按钮、用户注册…

QEMU源码全解析 —— virtio(2)

接前一篇文章&#xff1a; 本文内容参考&#xff1a; 《趣谈Linux操作系统》 —— 刘超&#xff0c;极客时间 《QEMU/KVM》源码解析与应用 —— 李强&#xff0c;机械工业出版社 特此致谢&#xff01; 上一回对于virtio进行了简介&#xff0c;并说明了其基本原理以及框架。对…

【JVM入门到实战】(三) 查看字节码文件的工具

一、 javap -v命令 javap是JDK自带的反编译工具&#xff0c;可以通过控制台查看字节码文件的内容。适合在服务器上查看字节码文件内容。直接输入javap查看所有参数。输入javap -v 字节码文件名称 查看具体的字节码信息。&#xff08;如果jar包需要先使用 jar –xvf 命令解压&a…

mmyolo的bbox_loss和检测bbox都是空

最近用mmyolo训练自己的数据集的时候发现训练的时候loss_bbox0&#xff0c;测试和eval的时候结果也全是空的&#xff0c;排除了数据集读取的问题&#xff0c;最后发现是config中自定义了自己的类别但是没有传给dataset。。。 简而言之&#xff0c;在自定义了数据集里的metainf…

深入理解Java虚拟机---内存分配

深入理解Java虚拟机---内存分配 GC日志内存分配与回收策略对象优先在Eden分配大对象直接进入老年代长期存活的对象将进入老年代动态对象年龄判定空间分配担保 GC日志 以下两段典型的GC日志&#xff1a; 33.125: [GC [DefNew: 3324K->152K(3712K), 0.0025925 secs] 3324K-&…

【C语言】一个RDMACM、Verbs API与epoll一起使用的例子

一、epoll介绍 epoll是Linux内核为处理大批量文件描述符而作了改进的poll&#xff0c;是Linux下多路复用IO接口select/poll的增强版本&#xff0c;它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。 以下是epoll的主要使用方法和优点&#xff1a; epo…

2023-12-05 Qt学习总结10

点击 <C 语言编程核心突破> 快速C语言入门 Qt学习总结 前言二十六 学生信息管理系统插入介绍: QTableView和QSqlTableModelQTableViewQSqlTableModel 程序所用数据库表格程序组成以及界面学生端源码:管理员端源码: 总结 前言 要解决问题: 学习qt最核心知识, 多一个都不…

Android : BottomNavigation底部导航_简单应用

示例图&#xff1a; 1.先创建底部导航需要的图片 res → New → Vector Asset 创建三个矢量图 图片1 baseline_home.xml <vector android:height"24dp" android:tint"#000000"android:viewportHeight"24" android:viewportWidth"24…

GEE机器学习——利用支持向量机SVM进行土地分类和精度评定

支持向量机方法 支持向量机(Support Vector Machine,SVM)是一种常用的机器学习算法,主要用于分类和回归问题。SVM的目标是找到一个最优的超平面,将不同类别的样本点分隔开来,使得两个类别的间隔最大化。具体来说,SVM通过寻找支持向量(即距离超平面最近的样本点),确定…

代码随想录 416. 分割等和子集

题目 使用二维dp数组思路 首先&#xff0c;我们需要计算整个数组的元素和 total_sum。如果 total_sum 是奇数&#xff0c;那么无论如何都无法将数组分成两个和相等的子集&#xff0c;因此直接返回 false。 然后&#xff0c;我们定义一个二维布尔数组 dp&#xff0c;其中 dp[i]…

nrm 的使用 可以快速切换下载(npm)镜像,解决资源下载慢和运行失败

nrm是什么&#xff1f; 介绍 nrm(npm registry manager) 是 npm 的镜像源管理工具. 有时候国外资源太慢,使用 nrm 可以快速的在 npm 源之间切换 安装 npm install -g nrm 基本使用 查看可选择的源 nrm ls 切换到对应的镜像源 nrm use 对应的镜像 删除镜像源 nrm del 名字 …

ArrayDeque阅读记录

前言&#xff1a; 1.对Queue接口进行实现 2.底层的数据结构还是数组&#xff0c;同时还是双向的&#xff0c;有前后指针 3.不是线程安全的 4.可以当作队列和栈来使用&#xff0c;选择使用队列时&#xff0c;ArrayDeque推荐首选 5.不可以添加null数据&#xff0c;会抛异常 …

深入理解 SVG:开启向量图形的大门(下)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

SQL注入漏洞的漏洞挖掘与利用

预计更新SQL注入概述 1.1 SQL注入攻击概述 1.2 SQL注入漏洞分类 1.3 SQL注入攻击的危害 SQLMap介绍 2.1 SQLMap简介 2.2 SQLMap安装与配置 2.3 SQLMap基本用法 SQLMap进阶使用 3.1 SQLMap高级用法 3.2 SQLMap配置文件详解 3.3 SQLMap插件的使用 SQL注入漏洞检测 4.1 SQL注入…

acwing算法提高之动态规划--背包模型(四)

目录 1 基础知识2 模板3 工程化 1 基础知识 暂无。。。 2 模板 暂无。。。 3 工程化 题目1&#xff1a;货币系统。 解题思路&#xff1a;完全背包模型求方案数。 状态定义f[i][j]&#xff1a;从前i个物品中选体积恰好为j的方案数。 状态转移f[i][j]&#xff0c;以下情况…