2015-09-12 40 views
0

我的機器上有4個內核。for-comprehension vs Future.sequence

而且我認爲換理解時間表的東西,在並聯機器人(不能夠在以前的result..same爲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) 

其中

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" 
     } 
    } 
    } 
} 

,但我看到的是(各步驟花費〜5秒):

  • 啓動服務1上ForkJoinPool -3-工人-5-
  • 上ForkJoinPool -3-工人-5-
  • 啓動服務
  • 開始服務2 ForkJoinPool -3-工人-5-
  • ERROR:java.util.concurrent.TimeoutException:期貨後[10秒]
  • 超時

全部運行在一個線程上,而不是使用現有的免費版本,並儘可能快地完成所有工作 - 大約需要5秒。

但是,如果我去:

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 } 
} 
.. 

所有以5秒結束。

pont for-understanding繼續工作嗎?可以?

回答

3

它不連續的工作,它只是直到他們被創建將​​創建無法啓動Future S(會發生在你的情況下,在你的flatMap你以前Future它),所以你需要預先創建它們,如果你想並行處理它們(通常隱含的ExecutionContext)。

大概this tutorial解釋更好,雖然(它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.

The for-comprehension above is translated into:

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. The flatMap operation maps its own value into some other future. 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. The resulting future purchase is completed only once this third future returned from map completes.

什麼你真的只需要的是像map2而不是flatMap,因爲你不從以前Future使用返回值創建新的Future

+0

doServiceStuff創建一個未來,如果它被調用。 (?) – ses

+0

@ses正確。兩者之間的區別在於,在第一種情況下,直到前一個'Future'的結果準備就緒纔會調用它(因爲您可以在'flatMap'中使用該值來使用'doServiceStuff'創建一個新的'Future') 。 –

+1

(不幸的是Scala沒有像'map2'這樣的方法來理解語法。) –

相關問題