Akka Streams:如何等待几个Flow完成

时间:2014-08-15 17:54:09

标签: scala akka akka-stream

我的程序中有几个Flow,我想并行处理。一切都完成后,我想触发一些行动。

执行此操作的一种方法是在每次完成后向Actor发送消息,并且当Actor验证所有流已准备就绪时,它可以触发操作。

我想知道是否有一些我可能会忽略的akka​​-streams Scala DSL中的任何东西会让它更简单。

修改: 将流转换为未来是行不通的,因为正如文档所述,Future在流中发生的第一个事件之后立即完成。运行以下代码:

implicit val system = ActorSystem("Sys")
val fm = FlowMaterializer(MaterializerSettings())

def main(args: Array[String]): Unit = {
  val fut = Flow(1 second, {() => println("tick")}).toFuture(fm)

  fut.onComplete{ _ =>
    println("future completed")
  }
}

打印“tick”,然后是“future completed”,然后是“tick”的无限序列。

2 个答案:

答案 0 :(得分:9)

正如评论中所提到的,我相信@Eduardo将Flow转换为Future是正确的。考虑这个例子:

implicit val system = ActorSystem("Sys")
import system.dispatcher

val text1 = 
  """hello1world
  foobar""".stripMargin

val text2 = 
  """this1is
  a1test""".stripMargin

def flowFut(text:String) = Flow(text.split("\\s").toVector)
  .map(_.toUpperCase())
  .map(_.replace("1", ""))
  .toFuture(FlowMaterializer(MaterializerSettings()))    


val fut1 = flowFut(text1)    
val fut2 = flowFut(text2)    
val fut3 = for{
  f1 <- fut1
  f2 <- fut2
} yield {
  s"$f1, $f2"
}

fut3 foreach {println(_)}

在这里,我在每组文本行上运行两个单独的变换,转换为upper并从任何文本中删除#1。然后,我将此Flow的结果强制为Future,以便我可以将结果合并为一个新的Future然后打印出来。

答案 1 :(得分:0)

哦,我明白了。如果流程处理多个元素,则未来将在第一个元素之后完成。

我认为您可以使用flow.onComplete来完成一些承诺。 e.g。

val promise1 = Promise[Unit]()
val promise2 = Promise[Unit]()

val flow1 = Flow(Iterator(1,2,3,4)).map(println)
val flow2 = Flow(Iterator('a,'b,'c,'d)).map(println)


flow1.onComplete(FlowMaterializer(MaterializerSettings())){
  case Success(_) =>  promise1.success()
  case Failure(e) => promise1.failure(e)
}
flow2.onComplete(FlowMaterializer(MaterializerSettings())){
  case Success(_) =>  promise2.success()
  case Failure(e) => promise2.failure(e)
}

for {
  e1<- promise1.future
  e2<- promise2.future
}{
  println(s"completed!")
}

如果另一方面想要在每个元素元组完成处理后做某事,你可以使用flow1.zip(flow2)来组合它们。