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

Scala Akka Streams中run()与runWith()的核心差异及适用场景

Akka Streams: run() 与 runWith() 的核心差异及适用场景

核心差异

1. 调用对象不同

  • run() 是 RunnableGraph 的专属方法,必须在完整构建流拓扑(包括明确指定要保留的物化值)后才能调用。
  • runWith() 是 Source 或 Flow 的便捷方法,允许直接附加一个 Sink 并触发流的物化,无需先显式构建 RunnableGraph。

2. 物化值控制不同

  • run() 返回的是构建 RunnableGraph 时通过 Keep 类(如 Keep.left、Keep.right、Keep.both)或自定义函数指定的物化值,可灵活选择保留源、Sink 或两者的物化值,甚至组合处理。
  • runWith() 默认返回附加的 Sink 的物化值,本质是 source.toMat(sink)(Keep.right).run() 的语法糖。

适用场景判断

使用 run() 的场景

  • 需要保留 Source 的物化值(例如 Source.queue 返回的队列引用),或同时保留源和 Sink 的物化值,或需要自定义组合两者的物化值。
  • 构建了复杂流拓扑(包含多个 Flow、分支等),需要显式控制流的物化逻辑。

使用 runWith() 的场景

  • 只关心 Sink 的物化值,或完全不需要任何物化值(例如简单打印、写入文件等操作)。
  • 编写简洁代码处理简单流场景:直接将 Source/Flow 连接到单个 Sink,无需额外的物化值控制。

示例代码解析

给出的两段代码功能完全等价:

import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.{Keep, Sink, Source}

object RunAndRunWith extends App {

  implicit val system: ActorSystem = ActorSystem("Run_RunWith")
  implicit val materializer: ActorMaterializer = ActorMaterializer()

  // 显式构建RunnableGraph,保留Sink的物化值后调用run()
  Source(1 to 10).toMat(Sink.foreach[Int](println))(Keep.right).run()
  // 使用runWith()快捷方式,效果与上面完全一致
  Source(1 to 10).runWith(Sink.foreach[Int](println))

}

runWith(Sink) 就是 toMat(Sink)(Keep.right).run() 的缩写,两者都会物化流并执行 Sink.foreach 打印数字的操作,返回的都是 Sink.foreach 的物化值(这里是 Future[Done],表示流完成的信号)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 19:50:24