等待与同时!fut.isCompleted
await vs while !fut.isCompleted
我有下一个代码:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
object Main extends App {
println("Hello, World!")
val fut = Future { Thread.sleep(10000); 21 + 21 }
while (!fut.isCompleted)
{}
println(fut.value)
}
使用 Await 代替 while 循环有什么好处?使用 while 循环更好吗?为什么?
我正在尝试了解 Scala Futures
谢谢
在 Scala 中使用异步代码,您可能会与一个框架进行交互,该框架将接受或提供 Future[T]
.
在生产环境中,不要等待 Future。
如果你真的需要这样做使用Await
:
import scala.concurrent.duration._
Await.result(fut, 1 minute) //will return the result
Await.ready(fut, 1 minute) //or just await for completion
两者都阻止,但关于您的问题,这里是 Scala 文档的一个片段:
尽管此方法是阻塞的,但 [[scala.concurrent.blocking 阻塞]] 的内部使用可确保底层 [[ExecutionContext]] 有机会正确管理阻塞。
要了解一些现实生活中的用例,请参阅您如何在 Play Framework 中定义异步操作。
Await
应该比 while
循环少 CPU-intensive。
大多数 Futures 的实现最终将使用 def tryAwait
from Promise
,您可以看到它正在使用 CompletionLatch
,它在幕后使用一些 low-level线程同步功能,这样它实际上可以停止调用线程,直到锁存器被释放。与此同时,您的 CPU 可以去做其他事情并“忽略”该线程。
与 while (!fut.isCompleted)
相反,后者将花费所有可能的 CPU 周期 运行 进行检查。
但是,正如@gatear 已经提到的,您通常不会调用 Await.ready(...)
。通常,您会将一些行为附加到 Future 上,以便在结果可用时它会 运行(即让 Future 告诉事情准备就绪,而不是像汽车后座上的 child ,不断地问“我们到了吗?”)。例如:
val loadGoogleHtml: Future[String] = /* ... */
loadGoogleHtml.onComplete {
case Success(html) => println(s"loaded google.com --\n$html")
case Failure(err) => err.printStackTrace()
}
或者您可以创建一个新的 Future 将一些 post-processing 应用于第一个 future,例如
val loadGoogleHtmlAsXml: Future[XML] = {
loadGoogleHtml.map { rawHtml => parseRawXml(rawHtml) }
}
使用 Future 的 要点 是当你有一些价值最终可用时帮助你(例如一些 IO 操作就像与远程服务器通信,或者在单独的线程上 运行 或 thread-pool 进行的长时间计算,其中结果通过回调函数进行通信; Future 是与 callback-based 设计互动的更好方式。
我有下一个代码:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
object Main extends App {
println("Hello, World!")
val fut = Future { Thread.sleep(10000); 21 + 21 }
while (!fut.isCompleted)
{}
println(fut.value)
}
使用 Await 代替 while 循环有什么好处?使用 while 循环更好吗?为什么?
我正在尝试了解 Scala Futures
谢谢
在 Scala 中使用异步代码,您可能会与一个框架进行交互,该框架将接受或提供 Future[T]
.
在生产环境中,不要等待 Future。
如果你真的需要这样做使用Await
:
import scala.concurrent.duration._
Await.result(fut, 1 minute) //will return the result
Await.ready(fut, 1 minute) //or just await for completion
两者都阻止,但关于您的问题,这里是 Scala 文档的一个片段:
尽管此方法是阻塞的,但 [[scala.concurrent.blocking 阻塞]] 的内部使用可确保底层 [[ExecutionContext]] 有机会正确管理阻塞。
要了解一些现实生活中的用例,请参阅您如何在 Play Framework 中定义异步操作。
Await
应该比 while
循环少 CPU-intensive。
大多数 Futures 的实现最终将使用 def tryAwait
from Promise
,您可以看到它正在使用 CompletionLatch
,它在幕后使用一些 low-level线程同步功能,这样它实际上可以停止调用线程,直到锁存器被释放。与此同时,您的 CPU 可以去做其他事情并“忽略”该线程。
与 while (!fut.isCompleted)
相反,后者将花费所有可能的 CPU 周期 运行 进行检查。
但是,正如@gatear 已经提到的,您通常不会调用 Await.ready(...)
。通常,您会将一些行为附加到 Future 上,以便在结果可用时它会 运行(即让 Future 告诉事情准备就绪,而不是像汽车后座上的 child ,不断地问“我们到了吗?”)。例如:
val loadGoogleHtml: Future[String] = /* ... */
loadGoogleHtml.onComplete {
case Success(html) => println(s"loaded google.com --\n$html")
case Failure(err) => err.printStackTrace()
}
或者您可以创建一个新的 Future 将一些 post-processing 应用于第一个 future,例如
val loadGoogleHtmlAsXml: Future[XML] = {
loadGoogleHtml.map { rawHtml => parseRawXml(rawHtml) }
}
使用 Future 的 要点 是当你有一些价值最终可用时帮助你(例如一些 IO 操作就像与远程服务器通信,或者在单独的线程上 运行 或 thread-pool 进行的长时间计算,其中结果通过回调函数进行通信; Future 是与 callback-based 设计互动的更好方式。