小心 Await.result
请注意,这适用于 Akka 和 play 应用程序
Await.result
只有在绝对必要时才应非常小心地使用。
Await.result
阻塞它正在运行的线程,直到给定的持续时间。阻塞线程将浪费宝贵的计算资源,因为该线程将无法进行任何有用的计算,例如处理新请求或算法中的数字运算等。
所以,尽量避免使用Await.result
。
但是,我们什么时候使用它(Await.result)?
这是使用Await.result
.
假设您编写了一个包含主线程的程序,并且主线程内的所有计算都是异步的。现在,一旦您在主线程内开始异步计算。有些人必须停止主线程的存在直到异步计算完成,否则程序停止运行并且您无法看到异步计算的结果。
当应用程序开始运行时,有一个非守护线程,其工作是执行 main()。除非非守护线程完成,否则 JVM 不会自行退出。
object Main {
def main(args: Array[String]): Unit = {
import scala.concurrent.Future
import scala.concurrent.duration._
val f = Future { //do something }
//stop main thread till f completes
Await.result(f, 10 seconds)
}
}
Future 使用守护线程来运行。所以守护线程不能阻止JVM关闭。因此,即使非守护线程正在运行,JVM 也会关闭。
在上述情况下,f
如果不是主线程退出并且计算停止,则没有其他方法可以期望停止(阻塞)主线程直到计算完成。
在大多数情况下,您不需要使用Await.result
简单的Future
组合,使用map
和flatMap
就足够了。
使用 Await.result 的风险(通常所有阻塞代码)
基于事件的模型中的线程用完
在基于事件的模型中,如果您有需要很长时间才能返回的阻塞代码,您将很快耗尽线程。在 playframework 中,任何阻塞调用都可能降低应用程序的性能,并且应用程序会因为线程耗尽而变得非常缓慢。
在非基于事件的模型中内存不足
在每个请求模型的线程中。当您有阻塞呼叫需要很长时间才能退出/返回时。
情况 1:如果您有固定的线程池,则应用程序可能会用完线程。
情况 2:如果您有动态增长的线程池,那么您的应用程序将遭受过多的上下文切换开销,并且还会因为内存中的阻塞线程过多而耗尽内存。
在所有情况下,除了等待某些 IO 或其他事件之外,没有完成任何有用的工作。