You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何publishOn()会影响前置Mono.fromRunnable()的执行线程?

为什么publishOn()会影响Mono.fromRunnable()的执行线程?

测试代码

Mono.fromRunnable(() -> log.info("Thread {}", Thread.currentThread().getName()))
        .publishOn(Schedulers.boundedElastic())
        .subscribe();

日志输出

Thread boundedElastic-<x>

更换调度器时,线程名称会对应变化,这并非偶然。核心疑问是:为什么publishOn()调度器会影响Mono.fromRunnable()中lambda表达式的执行线程?

按照Reactor文档的描述,publishOn()本应仅影响下游操作,比如下面这个符合预期的示例:

对比示例代码

Mono.just("x")
        .doOnNext(_w -> log.info("Thread before {}", Thread.currentThread().getName()))
        .publishOn(Schedulers.boundedElastic())
        .doOnNext(_w -> log.info("Thread after {}", Thread.currentThread().getName()))
        .subscribe();

对应日志输出

Thread before Test worker
Thread after boundedElastic-<x>

原因解析

问题的核心在于Mono.fromRunnable的延迟执行特性:

  1. fromRunnable不会立刻执行传入的任务,而是将其封装为一个“懒加载”的数据源——只有当订阅发生时,这个Runnable才会被触发执行。
  2. publishOn的作用是指定订阅后整个数据流的执行上下文,包括上游那些延迟执行的任务逻辑。

在第一个测试代码中,调用subscribe()时,整个数据流的执行会切换到publishOn指定的boundedElastic调度器线程池,fromRunnable里的任务自然就在该线程中执行,所以日志显示的是调度器线程名称。

而在对比示例中,Mono.just("x")是已就绪的数据源(创建时就生成了数据),publishOn之前的doOnNext会在订阅线程(这里是Test worker)上执行;publishOn之后的下游操作才会切换到指定调度器线程,这就是我们对publishOn“仅影响下游”的常规认知场景。

总结

  • 对于延迟执行的上游数据源(如fromRunnable、fromCallable),publishOn会影响其执行线程,因为它们的触发时机在订阅阶段,此时上下文已被调度器接管。
  • 对于已就绪的上游数据源(如just、from),publishOn仅会切换其下游操作的执行线程,上游逻辑不受影响。

内容的提问来源于stack exchange,提问作者rosik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 19:18:22