使用幻像时,在db调用中遵循此模式有多危险:
Await.result(dbOperationFut, 30.seconds)
这不是特定的幻像,但它是使用的scala驱动程序。
我厌倦了这种模式,因为潜在的GC暂停可能会持续超过x秒。 GC暂停时安全多少秒?
我个人赞成使用for-comp而不是像这样阻止,但只是想知道这是不是很糟糕的做法,或者它很好。
上下文:这适用于基于akka的应用程序(akka,akka http)
思想?
答案 0 :(得分:2)
对Await.result感到满意
请注意,这适用于Akka和播放应用
只有在绝对必要时才应非常小心地使用
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或其他事件都无法完成任何有用的工作。