Akka Stream中的map和mapAsync(1)的结果

时间:2016-03-19 08:59:53

标签: scala akka akka-stream

我使用mapAync(1)的代码无法正常运行。但是当我使用mapAsync(1)map更改为Await.result时,它就可以了。所以我有一个问题。 以下(A) Use map(B) use mapAsync(1)会随时产生相同的结果吗?

// (A) Use map
someSource
 .map{r => 
   val future = makeFuture(r) // returns the same future if r is the same
   Await.result(future, Duration.Inf)
 }

// (B) Use mapAsync(1)
someSource
 .mapAsync(1){r =>
   val future = makeFuture(r) // returns the same future if r is the same
   future
}

实际上,我想粘贴我的真实代码,但是粘贴时间太长而且我的原始阶段有一些依赖性。

2 个答案:

答案 0 :(得分:3)

虽然在语义上两个流的类型最终相同(Source[Int, NotUsed]),但示例(A)中显示的样式非常糟糕 - 请不要阻止({{1}内部流。

此类案例正是Await的用例。您的操作返回mapAsync,并且您希望在将来完成后将该值向下推送到流中。请注意,mapAsync中有无阻塞,它会调度回调以在内部推送未来值,并在完成后执行此操作。

要回答关于"他们做同样事情的问题?",技术上是,但第一个会导致您正在运行的线程池中的性能问题,避免地图+阻止时mapAsync可以完成这项工作。

答案 1 :(得分:1)

这些调用在语义上非常相似,尽管使用Await进行阻塞可能不是一个好主意。这些调用的类型签名当然是相同的(Source[Int, NotUsed]),并且在许多情况下这些调用将产生相同的结果(阻塞)。例如,以下内容包括计划期货和失败的非默认监管策略,对于内部有Await和mapAsync的地图都给出了相同的结果:

import akka.actor._
import akka.stream.ActorAttributes.supervisionStrategy
import akka.stream.Supervision.resumingDecider
import akka.stream._
import akka.stream.scaladsl._

import scala.concurrent._
import scala.concurrent.duration._
import scala.language.postfixOps

object Main {

  def main(args: Array[String]) {

    implicit val system = ActorSystem("TestSystem")
    implicit val materializer = ActorMaterializer()
    import scala.concurrent.ExecutionContext.Implicits.global
    import system.scheduler

    def makeFuture(r: Int) = {
      akka.pattern.after(2 seconds, scheduler) {
        if (r % 3 == 0)
          Future.failed(new Exception(s"Failure for input $r"))
        else
          Future(r + 100)
      }
    }

    val someSource = Source(1 to 20)

    val mapped = someSource
      .map { r =>
        val future = makeFuture(r)
        Await.result(future, Duration.Inf)
      }.withAttributes(supervisionStrategy(resumingDecider))

    val mappedAsync = someSource
      .mapAsyncUnordered(1) { r =>
        val future = makeFuture(r)
        future
      }.withAttributes(supervisionStrategy(resumingDecider))

    mapped runForeach println
    mappedAsync runForeach println

  }

}

您的上游代码可能以某种方式依赖地图调用中的阻止行为。您能否对您所看到的问题进行简洁的再现?