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 等),我可以针对场景详细分析。

相关推荐
梦梦代码精10 小时前
LikeShop按摩到家系统:2026年本地生活创业新风口,上门服务O2O源码私有化部署实战
大数据·docker·小程序·uni-app·生活·高并发·开源软件
代码讲故事5 天前
Redis生产环境批量的key需要删除,如何优雅实现且不影响线上环境?有密码认证的如何实现批量删除?有哪些实现方法?
运维·redis·缓存·高并发·删除·批量·生产环境
韩明君5 天前
Debian12安装RabittMQ 4.3.0
linux·debian·高并发·debian12·rabittmq
要开心吖ZSH6 天前
零基础入门 Spring WebFlux 与 Project Reactor:从小白到顿悟
java·响应式编程·spring webflux
YYYing.6 天前
【C++项目之高并发内存池 (五)】一些小细节和性能优化及整体测试
c++·性能优化·高并发·内存池·基数树
Lucis__7 天前
I/O多路复用:基于epoll实现Reactor高性能TCP服务器
linux·服务器·网络·reactor·多路复用
Cry丶7 天前
响应式流(Reactor)最佳实践指南
reactor·响应式编程·最佳实践·算子转换·归纳总结
Javatutouhouduan7 天前
2026Java面试的正确打开方式!
java·高并发·java面试·java面试题·后端开发·java编程·java八股文
YYYing.9 天前
【C++项目之高并发内存池 (四)】三层缓存的空间回收流程详解
c++·笔记·缓存·高并发·内存池
小杰31210 天前
网络框架源码阅读技巧
服务器·网络·c++·reactor·zlmediakit·zltoolkit