当前位置: 首页 > article >正文

Java 响应式编程最佳实践:构建高效的异步应用

Java 响应式编程最佳实践构建高效的异步应用别叫我大神叫我 Alex 就好。一、引言大家好我是 Alex。响应式编程作为一种编程范式已经在 Java 生态系统中变得越来越重要。随着 Spring WebFlux、Project Reactor 和 RxJava 等框架的普及响应式编程已经成为构建高性能、高并发应用的重要手段。今天我想和大家分享一下 Java 响应式编程的最佳实践帮助大家构建更高效的异步应用。二、响应式编程的核心概念1. 什么是响应式编程响应式编程是一种基于数据流和变化传播的编程范式。它的核心思想是数据流将应用的状态和事件表示为数据流变化传播当数据流发生变化时自动传播到依赖它的组件异步非阻塞使用异步非阻塞的方式处理数据流背压处理处理生产者和消费者之间的速率不匹配问题2. 响应式编程的优势响应式编程的主要优势包括高并发能够处理大量并发请求低延迟减少请求处理的延迟资源高效更有效地利用系统资源弹性更好地应对系统故障和负载变化可组合性易于组合和重用代码三、响应式编程框架1. Project ReactorProject Reactor 是 Spring 生态系统中的响应式编程框架Flux表示 0 到 N 个元素的异步序列Mono表示 0 到 1 个元素的异步序列Operators丰富的操作符用于处理数据流Schedulers调度器用于控制执行线程示例// 创建 Flux FluxInteger flux Flux.just(1, 2, 3, 4, 5); // 处理数据流 flux .map(i - i * 2) .filter(i - i 5) .subscribe(System.out::println); // 创建 Mono MonoString mono Mono.just(Hello); // 处理 Mono mono .map(s - s World) .subscribe(System.out::println);2. RxJavaRxJava 是一个流行的响应式编程库Observable表示 0 到 N 个元素的异步序列Single表示 0 到 1 个元素的异步序列Completable表示一个没有返回值的异步操作Flowable支持背压的 Observable示例// 创建 Observable ObservableInteger observable Observable.just(1, 2, 3, 4, 5); // 处理数据流 observable .map(i - i * 2) .filter(i - i 5) .subscribe(System.out::println); // 创建 Single SingleString single Single.just(Hello); // 处理 Single single .map(s - s World) .subscribe(System.out::println);3. Spring WebFluxSpring WebFlux 是 Spring 框架中的响应式 Web 框架注解驱动支持基于注解的控制器函数式端点支持函数式编程风格的端点定义Reactor 集成基于 Project ReactorNetty默认使用 Netty 作为服务器示例// 注解驱动控制器 RestController RequestMapping(/api/users) public class UserController { private final UserService userService; public UserController(UserService userService) { this.userService userService; } GetMapping public FluxUser getUsers() { return userService.getUsers(); } GetMapping(/{id}) public MonoUser getUser(PathVariable long id) { return userService.getUser(id); } } // 函数式端点 Configuration public class RouterConfig { Bean public RouterFunctionServerResponse route(UserHandler handler) { return RouterFunctions .route(GET(/api/users), handler::getUsers) .andRoute(GET(/api/users/{id}), handler::getUser); } } Component public class UserHandler { private final UserService userService; public UserHandler(UserService userService) { this.userService userService; } public MonoServerResponse getUsers(ServerRequest request) { return ServerResponse.ok() .body(userService.getUsers(), User.class); } public MonoServerResponse getUser(ServerRequest request) { long id Long.parseLong(request.pathVariable(id)); return userService.getUser(id) .flatMap(user - ServerResponse.ok().bodyValue(user)) .switchIfEmpty(ServerResponse.notFound().build()); } }四、响应式编程最佳实践1. 理解背压背压是响应式编程中的重要概念用于处理生产者和消费者之间的速率不匹配问题背压策略选择合适的背压策略流量控制使用操作符控制数据流的速率缓冲区合理使用缓冲区示例// 使用背压策略 Flux.range(1, 1000) .onBackpressureBuffer(100, () - System.out.println(Buffer full)) .subscribe(i - { // 模拟慢消费 try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(i); });2. 合理使用操作符响应式框架提供了丰富的操作符合理使用它们可以提高代码的可读性和效率转换操作符map、flatMap、concatMap 等过滤操作符filter、take、skip 等组合操作符merge、concat、zip 等错误处理操作符onErrorReturn、onErrorResume、retry 等示例// 转换操作符 Flux.just(a, b, c) .map(String::toUpperCase) .subscribe(System.out::println); // 过滤操作符 Flux.range(1, 10) .filter(i - i % 2 0) .subscribe(System.out::println); // 组合操作符 FluxInteger flux1 Flux.just(1, 2, 3); FluxInteger flux2 Flux.just(4, 5, 6); Flux.merge(flux1, flux2) .subscribe(System.out::println); // 错误处理操作符 Flux.just(1, 2, 3) .map(i - { if (i 2) { throw new RuntimeException(Error); } return i; }) .onErrorReturn(0) .subscribe(System.out::println);3. 正确处理错误错误处理是响应式编程中的重要环节错误传播理解错误在响应式流中的传播机制错误恢复实现合理的错误恢复策略错误日志适当记录错误信息示例// 错误恢复 Mono.just(key) .flatMap(key - { // 模拟可能出错的操作 if (key.equals(key)) { return Mono.error(new RuntimeException(Error)); } return Mono.just(value); }) .onErrorResume(e - { // 错误恢复 System.out.println(Error occurred: e.getMessage()); return Mono.just(default value); }) .subscribe(System.out::println);4. 合理使用调度器调度器用于控制响应式操作的执行线程选择合适的调度器根据操作类型选择合适的调度器避免线程切换减少不必要的线程切换并行处理合理使用并行处理示例// 使用不同的调度器 Flux.range(1, 10) .publishOn(Schedulers.parallel()) // 并行处理 .map(i - { System.out.println(Processing on thread: Thread.currentThread().getName()); return i * 2; }) .subscribeOn(Schedulers.boundedElastic()) // 订阅操作在 boundedElastic 线程池 .subscribe(i - System.out.println(Received on thread: Thread.currentThread().getName() , value: i));5. 避免阻塞操作响应式编程的核心是异步非阻塞应避免在响应式流中执行阻塞操作使用非阻塞 API优先使用非阻塞的 API封装阻塞操作如果必须使用阻塞操作应将其封装在适当的调度器中示例// 避免阻塞操作 // 错误示例 Flux.range(1, 10) .map(i - { // 阻塞操作 try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } return i * 2; }) .subscribe(System.out::println); // 正确示例 Flux.range(1, 10) .publishOn(Schedulers.boundedElastic()) .map(i - { // 阻塞操作 try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } return i * 2; }) .subscribe(System.out::println);6. 合理使用缓存缓存可以提高响应式应用的性能响应式缓存使用响应式缓存库缓存策略选择合适的缓存策略缓存失效合理处理缓存失效示例// 使用 Caffeine 缓存 CacheLong, User cache Caffeine.newBuilder() .expireAfterWrite(10, TimeUnit.MINUTES) .maximumSize(1000) .build(); // 响应式缓存 public MonoUser getUser(long id) { return Mono.defer(() - { User user cache.getIfPresent(id); if (user ! null) { return Mono.just(user); } return userRepository.findById(id) .doOnNext(cache::put); }); }五、响应式编程实战案例构建响应式 Web 服务需求构建一个响应式 Web 服务处理用户请求执行数据库操作和外部 API 调用。实现技术栈Spring Boot 4.3Spring WebFluxProject ReactorR2DBC (响应式数据库驱动)PostgreSQL代码// 响应式仓库 public interface UserRepository extends ReactiveCrudRepositoryUser, Long { FluxUser findByAgeGreaterThan(int age); } // 服务 Service public class UserService { private final UserRepository userRepository; private final WebClient webClient; public UserService(UserRepository userRepository, WebClient webClient) { this.userRepository userRepository; this.webClient webClient; } public FluxUser getUsers() { return userRepository.findAll(); } public MonoUser getUser(long id) { return userRepository.findById(id); } public MonoUser createUser(User user) { return userRepository.save(user); } public MonoUser getUserWithExternalData(long id) { return userRepository.findById(id) .flatMap(user - { // 调用外部 API return webClient.get() .uri(https://api.example.com/users/ id) .retrieve() .bodyToMono(ExternalUserData.class) .map(externalData - { user.setExternalData(externalData); return user; }); }); } } // 控制器 RestController RequestMapping(/api/users) public class UserController { private final UserService userService; public UserController(UserService userService) { this.userService userService; } GetMapping public FluxUser getUsers() { return userService.getUsers(); } GetMapping(/{id}) public MonoUser getUser(PathVariable long id) { return userService.getUser(id); } PostMapping public MonoUser createUser(RequestBody User user) { return userService.createUser(user); } GetMapping(/{id}/external) public MonoUser getUserWithExternalData(PathVariable long id) { return userService.getUserWithExternalData(id); } }结果系统能够处理大量并发请求响应时间显著减少资源使用更加高效系统更加弹性和可靠六、总结Java 响应式编程是构建高性能、高并发应用的重要手段。通过合理地应用响应式编程的最佳实践我们可以构建更高效、更可靠的异步应用。响应式编程的核心是理解数据流、背压处理和异步非阻塞的编程模型以及合理使用响应式框架提供的操作符和工具。这其实可以更优雅一点。希望这篇文章能帮助大家更好地理解和实践 Java 响应式编程的最佳实践。如果你有任何问题欢迎在评论区留言。关于作者我是 Alex一个在 CSDN 写 Java 架构思考的暖男。喜欢手冲咖啡养了一只叫Java的拉布拉多。如果我的文章对你有帮助欢迎关注我一起探讨 Java 技术的优雅之道。

相关文章:

Java 响应式编程最佳实践:构建高效的异步应用

Java 响应式编程最佳实践:构建高效的异步应用别叫我大神,叫我 Alex 就好。一、引言 大家好,我是 Alex。响应式编程作为一种编程范式,已经在 Java 生态系统中变得越来越重要。随着 Spring WebFlux、Project Reactor 和 RxJava 等框…...

从原理到选型:WDM波分复用技术全解析与应用指南

1. WDM波分复用技术基础入门 第一次接触WDM这个概念是在2013年参加某运营商骨干网改造项目时。当时客户指着机房密密麻麻的光纤问我:"能不能在不更换现有光缆的情况下,把传输容量提升8倍?"这个问题直接把我问住了。后来在华为专家的…...

台达PLC与C#串口通信实时监控:XML配置监控地址,控件自动生成读写同步操作

台达plc与C#串口通信程序,可同步读写操作,实时监控。 监控地址通过xml文件配置,控件自动生成。折腾工控通信的老铁们肯定都遇到过这问题——PLC和上位机要实时互传数据还得保证不卡顿。今天咱们就用C#和台达PLC的串口通信来盘一盘这个需求&am…...

基于WRF-DNN融合的气象数据降尺度技术实践与优化

1. 气象数据降尺度为什么需要WRF和DNN联手? 每次打开天气预报App查看未来几天的温度变化时,你可能不会想到背后需要处理TB级的气象数据。专业领域使用的WRF模型就像个严谨的老教授,擅长用物理公式推演天气变化,但有个致命弱点——…...

崖山数据库的体系架构

一、 数据库与数据库实例YashanDB数据库,英文名称叫做Yashan Database。这里所说的数据库是一个物理上的概念,即指物理操作系统的文件或者磁盘的集合。换句话来说,YashanDB数据库是由物理硬盘上许多的文件组成。这些文件包含了数据文件、控制…...

中文Python游戏开发避坑指南:植物大战僵尸开发中的5个常见问题及解决方案

Python游戏开发实战:植物大战僵尸复刻中的5个关键技术挑战 在游戏开发领域,Python凭借其简洁语法和丰富的库支持,成为许多独立开发者的首选语言。植物大战僵尸作为一款经典的塔防游戏,其核心玩法看似简单,但在实际开发…...

Mojo模块如何无缝注入PyTorch训练循环:从Cython替代到JIT热重载的完整链路(仅限内测版工具链公开)

第一章:Mojo模块如何无缝注入PyTorch训练循环:从Cython替代到JIT热重载的完整链路(仅限内测版工具链公开)Mojo模块通过原生ABI兼容层与PyTorch C前端深度对齐,无需修改torch.compile()调用栈即可嵌入训练循环。其核心机…...

RFSOC XCZU47DR在5G射频基带开发中的实战应用(含代码示例)

RFSOC XCZU47DR在5G射频基带开发中的实战应用(含代码示例) 在5G通信系统的开发中,射频基带处理一直是工程师面临的核心挑战之一。Xilinx的RFSOC XCZU47DR凭借其独特的架构设计,将高性能RF数据转换器与可编程逻辑完美融合&#xff…...

全球真空电子方向研究单位集锦

摘要:微波电子管是雷达、卫星、导弹、核聚变的核心 "心脏",也是全球少数几个真正的 "卡脖子" 技术之一。全世界能独立研制高端微波管的国家不超过 5 个,顶尖研究机构更是屈指可数。本文承接《微波电真空器件硬核科普》系…...

MetalLB才是给Ingress这个老登做负重前行的那个男人棺

一、核心问题及解决方案(按踩坑频率排序) 问题 1:误删他人持有锁——最基础也最易犯的漏洞 成因:释放锁时未做身份校验,直接执行 DEL 命令删除键。典型场景:服务 A 持有锁后,业务逻辑耗时超过锁…...

IP地址什么?工业场景网络注意事项有哪些?僬

OCP原则 ocp指开闭原则,对扩展开放,对修改关闭。是七大原则中最基本的一个原则。 依赖倒置原则(DIP) 什么是依赖倒置原则 核心是面向接口编程、面向抽象编程, 不是面向具体编程。 依赖倒置原则的目的 降低耦合度&#…...

从模型下载到API服务:手把手教你用MS-Swift+VLLM部署Qwen2.5-VL,打造自己的图像理解服务

从模型下载到API服务:手把手教你用MS-SwiftVLLM部署Qwen2.5-VL,打造自己的图像理解服务 在人工智能技术快速发展的今天,多模态大模型正逐渐成为理解和处理图像、文本等复杂数据的关键工具。Qwen2.5-VL作为一款强大的视觉语言模型,…...

Cross Q: Enhancing Deep Reinforcement Learning with Batch Normalization and Wide Critic Networks for

1. 深度强化学习的样本效率困境 深度强化学习(Deep Reinforcement Learning, DRL)近年来在游戏AI、机器人控制等领域取得了显著进展,但样本效率(Sample Efficiency)问题始终是制约其实际应用的瓶颈。简单来说&#xff…...

93.91%压缩率背后的技术革命:CompressO如何解决企业级视频处理的效率困境

93.91%压缩率背后的技术革命:CompressO如何解决企业级视频处理的效率困境 【免费下载链接】compressO Convert any video/image into a tiny size. 100% free & open-source. Available for Mac, Windows & Linux. 项目地址: https://gitcode.com/gh_mirr…...

5个核心策略解决Windows更新故障

5个核心策略解决Windows更新故障 【免费下载链接】Reset-Windows-Update-Tool Troubleshooting Tool with Windows Updates (Developed in Dev-C). 项目地址: https://gitcode.com/gh_mirrors/re/Reset-Windows-Update-Tool Windows更新是系统健康的重要保障&#xff0c…...

Nigate:Mac NTFS全功能读写解决方案——面向跨平台用户的高效文件交互指南

Nigate:Mac NTFS全功能读写解决方案——面向跨平台用户的高效文件交互指南 【免费下载链接】Free-NTFS-for-Mac Nigate: An open-source NTFS utility for Mac. It supports all Mac models (Intel and Apple Silicon), providing full read-write access, mounting…...

AI Agent 赋能智能客服:Vue3 + LangChain + 千问落地实战

前言 👋 本文适合有前端基础的开发者阅读。我会从整体架构出发,详解如何用Vue3 TypeScript做前端交互、**Python3 LangChain 千问(Qwen)**做后端推理,构建一个真正能落地的智能客服 Agent。代码干货较多&#xff0…...

RAGFlow实战:从零基础到构建企业级AI知识库

在2026年的今天,大模型(LLM)已经不再是新鲜事,但如何将这些“通才”模型转化为企业内部的“专才”,依然是技术落地的核心痛点。检索增强生成(RAG)技术应运而生,而RAGFlow作为一款开源…...

Docker+SyncTV+cpolar三件套:手把手教你搭建私人同步影院(附固定域名技巧)

DockerSyncTVcpolar三件套:打造高可用私人同步影院实战指南 在数字娱乐需求日益个性化的今天,私人影院的搭建已经从单纯的本地播放升级为兼具社交属性的协同体验。想象一下,无论好友身处何地,都能实时同步观看你精选的影片&#x…...

从删库到跑路?Oracle DBA必备的5种安全删除操作手册(附实战命令)

Oracle DBA安全删除操作全指南:从原理到实战 引言:为什么安全删除如此重要? 在数据库管理领域,删除操作可能是最令人胆战心惊的任务之一。想象一下这样的场景:凌晨三点,你接到紧急电话,因为一个…...

使用 Python 将 Excel 数据批量导入到数据库中(SQLite)

一、应用场景与方案优势适用场景企业 Excel 报表数据迁移至数据库持久化存储;自动化办公:定期将 Excel 导出数据同步到数据库;轻量级数据中台:多 Excel 文件整合入库,方便后续查询分析;4.测试数据构造&…...

点点库存管理小程序使用小技巧:两种采购方式搭配批量入库更省心

在库存管理系统的采购模块中,通常需要处理两种业务场景:常规采购(需上级审批)和紧急采购(免审批即时入库)。点点库存管理小程序同时支持这两种方式——生成待审核采购单与直接入库,并且均可搭配…...

2026年国内AI大厂薪资大揭秘:80万年薪不是梦?揭秘高薪背后的真相!

今天给大家盘一盘2026年国内几家主流AI大厂的薪资情况,数据主要来自招聘平台、社交媒体上的员工爆料,以及身边朋友的真实反馈。 最近两年,国内AI行业的人才争夺已经到了白热化的阶段,月之暗面、智谱AI、百川智能、MiniMax、DeepSe…...

IAR开发实战:如何用#pragma指令把C语言全局变量精准“钉”到指定RAM段(附完整icf配置)

IAR开发实战:全局变量精准定位到指定RAM段的高级技巧 在嵌入式开发中,内存管理一直是工程师们需要面对的挑战之一。当项目复杂度增加,性能要求提高时,如何高效地利用有限的RAM资源,将关键变量放置在最优位置&#xff0…...

告别Excel!用QT的QTableWidget打造你的第一个桌面端数据管理工具(附完整源码)

从Excel到专业桌面应用:基于QT的QTableWidget数据管理系统实战 在数据处理领域,Excel长期占据主导地位,但当数据量增长到数千行、需要复杂业务逻辑或多人协作时,电子表格的局限性就暴露无遗。许多开发者都面临过这样的困境&#x…...

小团队福音:用两台服务器搞定Redis高可用(Keepalived+互为主从配置)

小团队福音:用两台服务器构建轻量级Redis高可用架构 在初创公司和小型技术团队中,服务器资源往往捉襟见肘。当业务需要Redis作为缓存或数据库时,传统的高可用方案如哨兵模式需要至少三台服务器,这对资源有限的团队来说可能过于奢侈…...

合宙ESP32-C3用PlatformIO调试,别再为USB CDC和DIO配置头疼了

合宙ESP32-C3 PlatformIO调试实战:USB CDC与DIO配置全解析 第一次接触合宙ESP32-C3的开发板时,我被它简洁的设计和亲民的价格所吸引。但当我兴冲冲地打开PlatformIO准备大展拳脚时,却接连遇到了串口无法识别、程序下载失败等一系列问题。经过…...

汇川AM402 PLC控制IS620N伺服:手把手教你封装自己的轴控功能块(附完整工程)

汇川AM402 PLC控制IS620N伺服:从零封装轴控功能块的工程实践 在工业自动化项目中,伺服控制是最基础也最频繁使用的功能之一。想象一下,你正在开发一个包装产线控制系统,需要同时管理十几台伺服电机——每台电机都需要重复编写使能…...

Beyond Compare 5 许可证书生成与应用完全指南

Beyond Compare 5 许可证书生成与应用完全指南 【免费下载链接】BCompare_Keygen Keygen for BCompare 5 项目地址: https://gitcode.com/gh_mirrors/bc/BCompare_Keygen 一、问题剖析:许可管理核心挑战 1.1 评估期限制的实际影响 Beyond Compare 5作为专业…...

Binder使用方式及常见组成及案例分析

Binder 是 Android 核心的跨进程通信(IPC) 机制,以一次内存拷贝、内置安全校验、面向对象接口为核心优势,是系统服务与应用通信的基石。下面从核心组成、使用方式、实战案例、原理与常见问题四方面完整解析。一、Binder 核心组成&…...