news 2026/10/1 3:00:18

响应式编程入门:从 Mono 到 Flux 的实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
响应式编程入门:从 Mono 到 Flux 的实战指南

一、什么是响应式编程

传统编程是同步阻塞的:你调一个方法,线程停在那里等结果。

响应式编程是异步非阻塞的:你把任务声明好,交给框架,有结果了再通知你。核心思想是:

数据以流的形式流动,谁需要谁订阅。

Java 里最主流的响应式库是Reactor,Spring WebFlux 就是基于它。

二、两个核心类型

类型

元素个数

场景

Mono<T>

0 或 1 个

单个结果,比如查询、执行图

Flux<T>

0 到 N 个

流式数据,比如 SSE、多行输出

它们都是惰性的:不订阅就不会执行。

三、惰性执行

Mono<String> mono = Mono.fromCallable(() -> { System.out.println("执行了"); return "结果"; }); // 此时不会打印"执行了" mono.subscribe(); // 订阅后才执行,打印"执行了"

为什么惰性:框架可以把多个操作符组合成一条链,最后一次性执行,而不是每步都立即触发。

四、常见操作符

1. map —— 同步转换

Mono.just("abc").map(s -> s.length()); // Mono<Integer>

把每个元素同步转换成另一个值。

2. flatMap —— 异步转换

Mono.just("abc").flatMap(s -> Mono.just(s.length())); // Mono<Integer>

里面的 Lambda 返回一个Mono,flatMap会自动展平,避免Mono<Mono<T>>。

3. then —— 做完 A 再做 B

doA().then(doB());

忽略 A 的结果,A 完成后执行 B。

4. onErrorResume —— 异常兜底

前面任何一步出错,就返回兜底值,不让异常往上抛。

5. flatMapMany —— Mono 转 Flux

Mono<String>.flatMapMany(s -> Flux.just(s));

把一个Mono展开成Flux。

五、线程调度

1. subscribeOn —— 指定执行线程池

.subscribeOn(Schedulers.boundedElastic())

告诉 Reactor:这段代码在哪个线程池执行。

2. 常见 Schedulers

调度器

用途

线程数

immediate()

当前线程

不切换

single()

单线程

1

parallel()

CPU 密集

CPU 核数

boundedElastic()

阻塞 IO

CPU 核数 × 10

3. 为什么要切线程

因为数据库操作、HTTP 调用是阻塞的。如果直接在主线程执行:

  • 主线程被占住,无法处理其他请求。

  • 并发能力急剧下降。

用subscribeOn(boundedElastic())把阻塞操作挪到专用线程池,主线程继续处理其他请求。

六、阻塞 vs 非阻塞

对比项

阻塞(JDBC)

非阻塞(Reactor)

调用方式

同步

异步

线程行为

原地等

立即返回

返回值

结果本身

Mono/Flux

线程利用率

低

高

关键点:Mono本身是非阻塞的,但里面可以包装阻塞代码。用subscribeOn把阻塞代码挪走,就能避免拖累主线程。

七、链式调用

响应式代码是链式的,把多个操作串成一条流水线:

step1() .then(step2()) .flatMap(result -> step3(result)) .onErrorResume(e -> fallback()) .flatMapMany(Flux::just);

每个操作符返回新的Mono或Flux,可以继续链式操作。

八、和 CompletableFuture 的区别

对比项

CompletableFuture

Mono/Flux

惰性

否

是

元素个数

1 个

0~1(Mono)/ 0~N(Flux)

组合能力

有限

强,支持zip、merge、timeout

WebFlux 配合

需要包装

原生支持

空值表示

无

Mono.empty()

九、总结

概念

一句话

Mono

异步的 0 或 1 个结果

Flux

异步的 0 到 N 个结果

map

同步转换

flatMap

异步转换 + 展平

then

做完 A 再做 B

onErrorResume

异常兜底

flatMapMany

Mono 转 Flux

subscribeOn

指定执行线程池

boundedElastic

阻塞任务的专用线程池

核心思想:

声明式地描述“做什么”,而不是“怎么做”。

把多个异步操作串成一条链,由框架负责调度、组合、异常处理。

阻塞代码用subscribeOn挪到专用线程池,主线程保持非阻塞。

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

时序大数据预处理实战:从缺失值到异常检测的关键技术

搞大数据的人多半都听过一句话&#xff1a;垃圾进&#xff0c;垃圾出。模型再花哨、可视化再炫酷&#xff0c;只要喂进去的数据是脏的、缺的、乱的&#xff0c;最后的结果一定经不起推敲。而在整个大数据处理链路里&#xff0c;最容易被低估、又最直接决定项目成败的环节&#…

作者头像 李华
网站建设 2026/10/1 2:59:17

风格化渲染系统:从艺术规则到实时管线的工程实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/1 2:58:42

无人机树木识别及病害分析数据集| 树种识别 树木损伤 无人机航拍 林业监测 多视角检测 9133期

无人机树木识别及病害分析数据集| 树种识别 树木损伤 无人机航拍 林业监测 多视角检测 9133期 数据集概述 本数据集专注于无人机航拍视角下的树种分类与树木损伤检测&#xff0c;服务于林业资源调查、病害监测及生态保护。数据涵盖五种树木类别与两类损伤状态&#xff0c;适配树…

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

KKT条件详解:从拉格朗日乘子法到支持向量机的约束优化核心

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/1 2:57:41

CTF备赛实战指南:五大方向题型识别与工具链全解析

CTF 备赛这件事&#xff0c;最磨人的不是题目本身难&#xff0c;而是你根本不知道自己“该练什么”。刷题平台一大堆&#xff0c;题库上千道&#xff0c;结果今天做一道图片隐写&#xff0c;明天碰一道 Web 注入&#xff0c;后天又看到一个 PWN 题连环境都起不来&#xff0c;刷…

作者头像 李华
网站建设 2026/10/1 2:57:15

全月大收官:从0到300篇万行架构演进与全月商业化终审

全月大收官&#xff1a;从0到300篇万行架构演进与全月商业化终审今天是 2026 年 9 月 30 日&#xff08;周三&#xff09;。 当秋日金色的夕阳再次洒满书房的木质升降桌时&#xff0c;《AI 周报生成器从想法到收费的完整开发日志》专栏迎来了全月第 30 天的大圆满收官之战&…

作者头像 李华