深入理解 Scala Futures
Scala Futures in For Comprehension
我正在努力研究 Scala,我想知道以下内容的作用:
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
期货是在 for comprehension 内部执行的,对吗?那么 f
在 yield 语句中做了什么?这是否意味着它可用?如果这是在函数内部,那会被认为是 return value
吗?
在你的场景中,你不必使用 for comprehension,你可以简单地使用 OnComplete。
ffuture.OnComplete {
Case Success(result) => println(s"$result')
Case Failure(ex) => ex.printStackTrace
}
当你的未来依赖于其他未来时,就需要理解
喜欢:
var result = for {
f <- fFuture
g <- f
} yield g
这里g future 会在f 完成后解决,
并且 yield 将 return 无论你的结果是什么 returning。在这种情况下,它将是 Future[Int]。
使用 yield 你可以做类似的事情。
yield g+f
要读取结果,您只需使用
result.onSuccess or onComplete
对于 Futures,我发现这篇文章是最好的一篇:
http://alvinalexander.com/scala/concurrency-with-scala-futures-tutorials-examples
我会说是的,这类似于函数中的 return 值。
但这是为了理解语法,你不能使用 return 语句。
For comprehension is a better way to write map.
期货在这里开始执行:
val fFuture: Future[Int] = Future { println("f called"); 3 }
val gFuture: Future[Int] = Future { println("g called"); 4 }
所以两个执行是并行开始的。但是,如果您不小心将 Future{...}
放入 for-comprehension - 它们将按顺序执行。
For-comprehension 基本上订阅两个结果并将其合并为一个 Future。但是,在您的情况下,似乎忽略了第二个未来的结果,这是没有意义的。有意义的代码:
for {
f <- fFuture
g <- gFuture
} yield f + g
此代码 returns Future[Int]
(与示例中的代码相同)。如果你从这个 Future 中提取价值——你会得到 3 + 4 = 7
。然而,它仍然不是最佳方法,因为您的计算是独立的,并且开发人员错误(如上所述)导致它们顺序执行的可能性仍然很高,因此独立计算的推荐方法是:
(fFuture zip gFuture) map {
case (f, g) => f + g
}
这段代码是引用透明的,意思是即使你用 Future{...}
替换 fFuture
- 它仍然表现相同(在 Future
的情况下 - 它们将被执行并发,但对于其他并发原语可能有所不同)
for-comprehension
哪里有意义?这里:
for {
f <- Future{... 9}
g <- if (f > 0) Future{...} else Future{...}
} yield g
因为 g
依赖于 f
这里 - 没有办法 运行 并行,所以 for
提供了一种非阻塞的方式来组合几个 Future
s
Scala Futures 是急切求值的,这意味着它们的值会立即在单独的线程中计算。
当您 运行 依赖于未来结果的操作时,当前线程将阻塞等待直到它被评估。如果您使用 map 或 flatMap 等组合器方法转换 Future,您将获得另一个代表最终结果的 Future(代码 运行 执行这些操作不需要阻塞)。
因此在您的示例中,for 理解被编译器脱糖为以下表达式:
fFuture.flatMap(f => gFuture.map(g => f + g))
它本身是在另一个线程中计算的 Future[Int]。
我正在努力研究 Scala,我想知道以下内容的作用:
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
期货是在 for comprehension 内部执行的,对吗?那么 f
在 yield 语句中做了什么?这是否意味着它可用?如果这是在函数内部,那会被认为是 return value
吗?
在你的场景中,你不必使用 for comprehension,你可以简单地使用 OnComplete。
ffuture.OnComplete {
Case Success(result) => println(s"$result')
Case Failure(ex) => ex.printStackTrace
}
当你的未来依赖于其他未来时,就需要理解 喜欢:
var result = for {
f <- fFuture
g <- f
} yield g
这里g future 会在f 完成后解决, 并且 yield 将 return 无论你的结果是什么 returning。在这种情况下,它将是 Future[Int]。 使用 yield 你可以做类似的事情。
yield g+f
要读取结果,您只需使用
result.onSuccess or onComplete
对于 Futures,我发现这篇文章是最好的一篇: http://alvinalexander.com/scala/concurrency-with-scala-futures-tutorials-examples
我会说是的,这类似于函数中的 return 值。 但这是为了理解语法,你不能使用 return 语句。 For comprehension is a better way to write map.
期货在这里开始执行:
val fFuture: Future[Int] = Future { println("f called"); 3 }
val gFuture: Future[Int] = Future { println("g called"); 4 }
所以两个执行是并行开始的。但是,如果您不小心将 Future{...}
放入 for-comprehension - 它们将按顺序执行。
For-comprehension 基本上订阅两个结果并将其合并为一个 Future。但是,在您的情况下,似乎忽略了第二个未来的结果,这是没有意义的。有意义的代码:
for {
f <- fFuture
g <- gFuture
} yield f + g
此代码 returns Future[Int]
(与示例中的代码相同)。如果你从这个 Future 中提取价值——你会得到 3 + 4 = 7
。然而,它仍然不是最佳方法,因为您的计算是独立的,并且开发人员错误(如上所述)导致它们顺序执行的可能性仍然很高,因此独立计算的推荐方法是:
(fFuture zip gFuture) map {
case (f, g) => f + g
}
这段代码是引用透明的,意思是即使你用 Future{...}
替换 fFuture
- 它仍然表现相同(在 Future
的情况下 - 它们将被执行并发,但对于其他并发原语可能有所不同)
for-comprehension
哪里有意义?这里:
for {
f <- Future{... 9}
g <- if (f > 0) Future{...} else Future{...}
} yield g
因为 g
依赖于 f
这里 - 没有办法 运行 并行,所以 for
提供了一种非阻塞的方式来组合几个 Future
s
Scala Futures 是急切求值的,这意味着它们的值会立即在单独的线程中计算。
当您 运行 依赖于未来结果的操作时,当前线程将阻塞等待直到它被评估。如果您使用 map 或 flatMap 等组合器方法转换 Future,您将获得另一个代表最终结果的 Future(代码 运行 执行这些操作不需要阻塞)。
因此在您的示例中,for 理解被编译器脱糖为以下表达式:
fFuture.flatMap(f => gFuture.map(g => f + g))
它本身是在另一个线程中计算的 Future[Int]。