Reactor线程池切换publishOn与subscribeOn

在 Reactor(Project Reactor)中,publishOnsubscribeOn 是用于 切换执行线程(调度器) 的两个操作符,但它们的行为和用途 截然不同。下面是它们的详细区别与使用说明。


🧠 一句话理解

  • **subscribeOn**:指定源(Publisher)创建 & 订阅逻辑运行在哪个线程。
  • **publishOn**:指定后续操作符运行在哪个线程(从当前开始切换)。

🔁 subscribeOn:影响订阅动作及其"上游"

java 复制代码
Mono.fromCallable(() -> {
    log.info("Generating value");
    return "Hello";
})
.subscribeOn(Schedulers.boundedElastic()) // 👈 切换线程
.map(v -> {
    log.info("Mapping: {}", v);
    return v.toUpperCase();
});

📌 说明:

  • subscribeOn 会影响:
    • 源数据的创建(如 fromCallableMono.just
    • 源的订阅行为
    • 上游所有逻辑(在链条中靠前)

🧪 输出结果中的 log 会显示 Generating valueMapping: xxx 都在 boundedElastic 线程中执行。


🔀 publishOn:影响后续操作符

java 复制代码
Mono.fromCallable(() -> {
    log.info("Generating value");
    return "Hello";
})
.publishOn(Schedulers.parallel()) // 👈 从这里切换线程
.map(v -> {
    log.info("Mapping: {}", v);
    return v.toUpperCase();
});

📌 说明:

  • publishOn 只影响后续操作符的执行线程
  • 当前位置之后的操作符都在新的线程中执行
  • 当前位置之前的执行线程不会受影响

🧪 输出 log:

plain 复制代码
[main] Generating value
[parallel-1] Mapping: Hello

⚠️ 两者配合使用

java 复制代码
Mono.fromCallable(() -> {
    log.info("Generating value");
    return "Hello";
})
.subscribeOn(Schedulers.boundedElastic())
.publishOn(Schedulers.parallel())
.map(v -> {
    log.info("Mapping: {}", v);
    return v.toUpperCase();
});

🧪 输出 log:

plain 复制代码
[boundedElastic-1] Generating value
[parallel-1] Mapping: Hello

🔍 总结对比表

特性 subscribeOn publishOn
生效位置 整个流的最上游(首次调用生效) 只影响之后的操作符
常用于 指定数据源的线程(IO、慢操作) 指定数据处理的线程
多次调用 只有第一次调用有效(对源) 可以多次调用,影响每一处之后
应用场景 创建慢资源(数据库、文件等) 控制不同阶段逻辑在不同线程
替代线程切换逻辑 可以代替传统线程池包装异步逻辑 用于流中间切线程做不同的隔离或调度

✅ 实践建议

  • 网络/IO/阻塞调用 ➜ 放在 subscribeOn(Schedulers.boundedElastic())
  • 业务计算阶段 ➜ 用 publishOn(Schedulers.parallel()) 来提高并发度
  • 不要滥用这两个操作符,频繁切线程反而会增加上下文切换成本

如你有具体的使用场景(如 Flux + WebClient、文件读取、Kafka 等),我可以针对场景详细分析。

相关推荐
晴空蓝天6 天前
SpringBoot+Vue 招聘系统实战:解决简历投递高并发重复提交问题(附源码)
高并发·招聘系统·springboot实战
Code额10 天前
Python asyncio 异步编程全套学习文档(零基础完整版)
python·学习·oracle·async·异步·asyncio
会编程的土豆13 天前
12306 春运抢票:数据一致性怎么保证
redis·消息队列·go·高并发
啦啦啦啦啦zzzz15 天前
muduo网络库 TcpServer
服务器·网络·c++·reactor·网络库
啦啦啦啦啦zzzz16 天前
moduo网络库 Acceptor TcpConnection
服务器·网络·c++·reactor·网络库
智码看视界17 天前
Day 45 | Sentinel流量治理:从限流到熔断降级再到系统自适应保护
sentinel·高并发·熔断降级·流量控制·微服务治理·热点参数限流
XiaoLeisj17 天前
Kotlin Flow 常用操作符:数据变换 map、filter、onEach,时间控制 debounce、sample,终端聚合 reduce、fold
android·kotlin·android jetpack·协程·响应式编程·flow
wwwzhouzy18 天前
SpringBoot 响应式编程
java·spring boot·后端·响应式编程
行者-全栈开发22 天前
SpringBoot 4.x 迁移实战指南:从3.x平滑升级的完整方案与避坑经验
响应式编程·springframework·jakarta ee·virtual threads·springboot 4.x·版本迁移·升级指南
逻极1 个月前
FastAPI 实战:从入门到自动化文档,如何把API开发效率提升200%
python·api·fastapi·swagger·异步