Scala 如何解释官方文件中的Akka流图?
对于这个正式托管的示例代码,我有几个问题:Scala 如何解释官方文件中的Akka流图?,scala,akka,akka-stream,Scala,Akka,Akka Stream,对于这个正式托管的示例代码,我有几个问题: 何时通过创建传入图形 为什么topHeadSink、bottomHeadSink是通过create传入的,而sharedDoubler不是?他们之间有什么区别 何时需要builder.add 我是否可以在没有builder.add的情况下在图形外部创建广播?如果我在图中添加了几个流,我是否也应该通过builder.add添加流?有时我们需要builder.add,有时我们不需要,这是非常令人困惑的 更新 我觉得这仍然令人困惑: 这些方法之间的区别在于,
创建传入图形
topHeadSink、bottomHeadSink
是通过create传入的,而sharedDoubler
不是?他们之间有什么区别
builder.add
builder.add的情况下在图形外部创建广播?如果我在图中添加了几个流,我是否也应该通过builder.add
添加流?有时我们需要builder.add
,有时我们不需要,这是非常令人困惑的
更新
我觉得这仍然令人困惑:
这些方法之间的区别在于,使用builder.add(…)
导入会忽略导入图形的物化值,而通过factory方法导入则允许包含该值
topHS、bottomHS
是从create
导入的,因此它们将保留其物化值。如果我执行builder.add(topHS)
,该怎么办
您如何解释sharedDoubler:它是否具有物化值?如果我使用builder.add
,该怎么办
这是什么意思,GraphDSL.create(topHeadSink,bottomHeadSink)((,))的(((,))
它看起来像是我们需要的样板,但我不确定它是什么
什么时候通过create传入图形
当您想要获得传递给create
factory方法的图形的物化值时。您问题中的RunnableGraph
类型是RunnableGraph[(未来[Int],未来[Int])]
,这意味着图形的物化值是(未来[Int],未来[Int])
:
现在考虑下面的变体,它定义了图中的“汇”,并丢弃了物化值:
val g2 = RunnableGraph.fromGraph(GraphDSL.create() { implicit builder =>
import GraphDSL.Implicits._
val topHeadSink = Sink.head[Int]
val bottomHeadSink = Sink.head[Int]
val broadcast = builder.add(Broadcast[Int](2))
Source.single(1) ~> broadcast.in
broadcast.out(0) ~> sharedDoubler ~> topHeadSink
broadcast.out(1) ~> sharedDoubler ~> bottomHeadSink
ClosedShape
}).run() // NotUsed
g2
的值为未使用
何时需要builder.add
图形的所有组件都必须添加到生成器中,但是有一些操作符的变体可以将最常用的组件(如源和流)添加到生成器中。但是,执行扇入(如合并
)或扇出(如广播
)的连接操作必须显式传递给生成器。如果使用图形DSL,则添加
请注意,对于简单的图形,您可以使用连接,而不必使用图形DSL。以下是来自以下方面的示例:
这是什么意思?创建(TopHeadsLink,BottomHeadsLink)((,))
的((,))
它是一个curried参数,指定要保留的具体化值。这里使用的((,))
与:
val g = RunnableGraph.fromGraph(GraphDSL.create(topHeadSink, bottomHeadSink)((t, b) => (t, b)) {
implicit builder => (topHS, bottomHS) =>
...
}).run() // (Future[Int], Future[Int])
换句话说,((,))
在本文中是((t,b)=>(t,b))
的缩写,它保留传入的两个接收器的各自物化值。例如,如果只想保留topHeadSink
的物化值,可以将调用更改为以下内容:
val g = RunnableGraph.fromGraph(GraphDSL.create(topHeadSink, bottomHeadSink)((t, _) => t) {
implicit builder => (topHS, bottomHS) =>
...
}).run() // Future[Int]
谢谢@chunjef!答案很好。对于sharedDoubler
,我还有一个问题,它没有经过create
,也没有在图中创建,它的物化值会发生什么变化?为什么我们有两种方法将图形传递到另一种?一个通过创建
,一个不创建?或者流不保留物化的值?所以您只需要通过创建添加源、汇?
val sendRmotely = Sink.actorRef(actorRef, "Done")
val localProcessing = Sink.foreach[Int](_ => /* do something usefull */ ())
val sink = Sink.combine(sendRmotely, localProcessing)(Broadcast[Int](_))
Source(List(0, 1, 2)).runWith(sink)
val g = RunnableGraph.fromGraph(GraphDSL.create(topHeadSink, bottomHeadSink)((t, b) => (t, b)) {
implicit builder => (topHS, bottomHS) =>
...
}).run() // (Future[Int], Future[Int])
val g = RunnableGraph.fromGraph(GraphDSL.create(topHeadSink, bottomHeadSink)((t, _) => t) {
implicit builder => (topHS, bottomHS) =>
...
}).run() // Future[Int]