等待与同时!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 设计互动的更好方式。