简体   繁体   English

理解力与未来顺序

[英]for-comprehension vs Future.sequence

There are 4 cores on my machine. 我的机器上有4个核心。

And I thought that for-comprehension schedules stuff in paraller (not to be depended on previous result..same as flatMap): 而且我认为全面理解可以并行安排进度(不依赖于先前的结果..与flatMap相同):

val stuffResult: Future[String] = for {
   stuff1 <- service1.doServiceStuff("service 1")  // worker-5 (4+1)
   stuff2 <- service1.doServiceStuff("service 2")
   stuff3 <- service1.doServiceStuff("service 3")
   stuff4 <- service1.doServiceStuff("service 4")
 } yield (stuff1 + ", " + stuff2 + ", "+ stuff3 + ", " + stuff4)

where 哪里

 class Service {

 implicit val blockingExContext = scala.concurrent.ExecutionContext.fromExecutor(null: Executor)

 def doServiceStuff(name:String): Future[String] = {
    Future {
      blocking {    
        println ( s"start ${name} on " + Thread.currentThread.getName)
        Thread.sleep(5000)
        "stuff_done"
      }
    }
  }
}

But what i see is (each step takes ~5 seconds): 但是我看到的是(每个步骤大约需要5秒钟):

  • start service 1 on ForkJoinPool-3-worker-5 在ForkJoinPool-3-worker-5上启动服务1
  • start service 2 on ForkJoinPool-3-worker-5 在ForkJoinPool-3-worker-5上启动服务2
  • start service 3 on ForkJoinPool-3-worker-5 在ForkJoinPool-3-worker-5上启动服务3
  • ERROR:java.util.concurrent.TimeoutException: Futures timed out after [10 seconds] 错误:java.util.concurrent.TimeoutException:期货在[10秒]后超时

all runs on one thread, instead of use existing FREE one and finish all as fast as possible - in ~5 secs. 所有程序都在一个线程上运行,而不是使用现有的免费程序,并以最快的速度完成所有操作-只需约5秒。

But if I go with: 但是如果我选择:

val stuff1 = service1.doServiceStuff("service 1")
val stuff2 = service1.doServiceStuff("service 2")
val stuff3 = service1.doServiceStuff("service 3")
val stuff4 = service1.doServiceStuff("service 4")

Future.sequence(List(stuff1, stuff2, stuff3, stuff4)).map { list =>
  list.foldLeft("") { (acc, x) => acc + " " + x }
}
..

all ends in 5 second. 全部在5秒内结束。

At which pont for-comprehension works sequentially? 哪个pont理解能力会依次起作用? Does it? 可以?

It does not work sequentially, it just cannot start the Future s till they are created (which would happen in your case in your flatMap of your previous Future ), so you need to create them in advance if you want to process them in parallel (with the usual implicit ExecutionContext s). 它不能顺序工作,它只能在创建Future之前启动(在您的前一个Future flatMap ,这会发生),因此,如果要并行处理它们,则需要提前创建它们(以及通常的隐式ExecutionContext )。

Probably this tutorial explains better though (it complicates it with withFilter ): 不过, 本教程可能解释得更好(它使withFilter变得复杂):

The purchase future is completed only once both usdQuote and chfQuote are completed– it depends on the values of both these futures so its own computation cannot begin earlier. 仅在usdQuote和chfQuote均完成后,购买期货才完成–它取决于这两个期货的值,因此其自身的计算不能更早地开始。

The for-comprehension above is translated into: 上面的理解翻译为:

val purchase = usdQuote flatMap { usd => chfQuote .withFilter(chf => isProfitable(usd, chf)) .map(chf => connection.buy(amount, chf)) } val purchase = usdQuote flatMap { usd => chfQuote .withFilter(chf => isProfitable(usd, chf)) .map(chf => connection.buy(amount, chf)) }

which is a bit harder to grasp than the for-comprehension, but we analyze it to better understand the flatMap operation. 这比理解要难一点,但是我们对其进行分析以更好地理解flatMap操作。 The flatMap operation maps its own value into some other future. flatMap操作将其自身的价值映射到其他未来。 Once this different future is completed, the resulting future is completed with its value. 一旦完成了这个不同的未来,就将以其价值完成最终的未来。 In our example, flatMap uses the value of the usdQuote future to map the value of the chfQuote into a third future which sends a request to buy a certain amount of Swiss francs. 在我们的示例中,flatMap使用usdQuote期货的价值将chfQuote的价值映射到第三个期货中,该期货发送了购买一定数量瑞士法郎的请求。 The resulting future purchase is completed only once this third future returned from map completes. 只有从地图返回的第三个未来完成后,才能完成最终的未来购买。

What you would really only need is something like map2 instead of flatMap , as you do not use the returned value from the previous Future to create the new Future . 您真正需要的只是诸如map2之类的东西,而不是flatMap类的东西,因为您不使用前一个Future的返回值来创建新的Future

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM