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

相关推荐
睡不醒男孩03082313 天前
云原生运维实战:高并发架构下的云原生可观测性、韧性降级与自动化干预体系
数据库·kubernetes·高并发·prometheus·devops·sre·缓存调优
luoyayun36114 天前
Qt 中使用 QtConcurrent::run + QFutureWatcher 实现异步处理
qt·异步·qtconcurrent
星辰_mya15 天前
限流、漏斗桶和令牌桶的区别
java·开发语言·面试·架构·高并发
东南门吹雪17 天前
JAVA TCP socket编程框架
java·高并发·socket·tcp·nio
YYYing.18 天前
【C++大型项目之高性能服务器框架 (一) 】一切物语的开始:日志系统&配置系统篇
服务器·高并发·高性能·c/c++·后端框架
Momo__19 天前
alien-signals — 驱动 Vue 3.6 响应式引擎的那个 1KB 库
前端·vue.js·响应式编程
梦想的颜色19 天前
Kafka内核解密:架构拓扑、数据流转与生产消费模型的深度剖析
kafka·高并发·多线程·异步·消息组件·生产者与消费者模式
西凉的悲伤20 天前
多线程彻底掌握 CompletableFuture:从入门到项目实战
java·多线程·future·completable·异步
梦想的颜色22 天前
Redis数据类型全解析:从底层原理到生产实战
运维·数据库·redis·缓存·高并发·分布式锁·数据类型
Java爱好狂.25 天前
Java高并发系统架构设计核心技术开源!
java·高并发·并发编程·java面试·java面试题·java程序员·java八股文