2016-11-13 139 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]在另一个线程计算。