2016-11-13 192 views
0

我試圖總結我的周圍斯卡拉頭,我知道什麼是下列情況:斯卡拉期貨對於理解

val fFuture: Future[Int] = Future { println("f called"); 3 }                              
val gFuture: Future[Int] = Future { println("g called"); 4 }                              

for { 
    f <- fFuture 
    g <- gFuture 
} yield f 

該期貨的理解力,對內部執行?那麼f在收益率表中做了什麼?這是否意味着它可用?這是否被認爲是return value,如果這是在一個函數內?

+2

「未來」並未在'for'內執行。它們在聲明(總是)時執行,並使用'for'組成。 – cchantep

+1

@cchantep從技術上講,只有當ExecutionContext決定執行它們時纔會執行它們。 –

+0

正如我應該說的那樣,由歐盟決定一次執行,因爲它們的聲明很可能(在那裏很重要)在聲明和'for'之前,沒有可預測的順序,因爲這些'Future'不依賴於彼此。 – cchantep

回答

3

期貨開始在這裏執行:

val fFuture: Future[Int] = Future { println("f called"); 3 }                              
val gFuture: Future[Int] = Future { println("g called"); 4 } 

因此,無論執行並行開始。但是,如果您不小心將Future{...}置於理解範圍內,它們將按順序執行。

For-comprehension基本上訂閱併合併成一個未來的兩個結果。然而,就你而言,似乎第二個未來的結果被忽略了,這是沒有道理的。代碼有意義:

for { 
    f <- fFuture 
    g <- gFuture 
} yield f + g 

此代碼返回Future[Int](與您的示例中的代碼相同)。如果你從這個未來提取價值 - 你得到3 + 4 = 7。但是它仍然不是你的計算是獨立開發者的錯誤(如上所述)的可能性,這使得它們的順序仍然是高一個最好的方法,進行獨立計算,因此推薦的做法是:

(fFuture zip gFuture) map { 
    case (f, g) => f + g 
} 

此代碼是在引用透明這意味着即使你與Future{...}替換fFuture - 它仍然表現相同(在Future -they're將在prallel執行,但情況下,它可能是其他併發原語不同)

會在哪裏for-comprehension實際意義?在這裏:

for { 
    f <- Future{... 9} 
    g <- if (f > 0) Future{...} else Future{...} 
} yield g 

由於g取決於f這裏 - 有沒有辦法來運行這些並行,所以for提供作曲幾個Future小號

-2

這裏在你的場景中,你不必使用理解,你可以簡單地使用OnComplete。

ffuture.OnComplete { 
Case Success(result) => println(s"$result') 
Case Failure(ex) => ex.printStackTrace 
} 

對於理解當你有未來(S)依賴於其他未來(S) 一樣需要:

var result = for { 
     f <- fFuture 
     g <- f 
    } yield g 

這裏˚F完成後摹未來將得到解決, 和產量將返回無論你回來的結果如何。在這種情況下,它將成爲Future [Int]。有了產量,你可以做類似的事情。

yield g+f 

要閱讀的結果,你可以簡單地使用

result.onSuccess or onComplete 

對於期貨,我發現這篇文章是最好的一個: http://alvinalexander.com/scala/concurrency-with-scala-futures-tutorials-examples

我會說是的,這是類似的返回值在一個函數中。 但是這是理解語法,你不能使用return語句。 理解是編寫地圖的更好方法。

+0

如果你能解釋不喜歡的原因,這將是很大的幫助,我會學到新的東西。 – user2056463

1

斯卡拉期貨的非阻塞的方式都在熱切評估,這意味着它們的值立即在單獨的線程中計算。

當您運行依賴於未來結果的操作時,當前線程將阻止等待,直到它被評估爲止。如果您使用combinator方法(例如map或flatMap)轉換Futures,則會得到另一個Future來表示最終結果(運行這些操作的代碼不需要阻止)。

因此,在您的示例的理解是由編譯器脫下列表達式:

fFuture.flatMap(f => gFuture.map(g => f + g)) 

這本身就是一個未來[INT]在另一個線程計算。