假设我有一个提供许多请求的应用程序。其中一个请求需要一段时间才能完成。我有以下代码:
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.concurrent.Await
import scala.concurrent.Future
def longReq(data:String):String = {
val respFuture = Future{
// some code that computes resp but takes a long time
// can my application process other requests during this time?
resp = ??? // time-consuming step
}
Await.result(respFuture, 2 minutes)
}
如果我根本不使用期货,应用程序将被阻止,直到计算出resp
并且在此期间不能并行提供其他请求。但是,如果我使用期货然后使用resp
阻止Await
,那么应用程序是否能够在计算resp
的同时并行处理其他请求?
答案 0 :(得分:3)
在您的特定示例中,假设请求循环按顺序调用longReq
,答案为否,它无法处理任何其他内容。因为longReq
必须返回未来:
def longReq(data:String): Future[String] = {
Future {
// some code that computes resp but takes a long time
// can my application process other requests during this time?
resp = ??? // time-consuming step
}
}
当然,这只会推动您可能使用Await.result
的原因。
使用Future
的目的是为了避免阻止,但这是一个乌龟 - 所有向下买入。如果您想使用Future
,最终收件人必须能够处理以异步方式获取结果,即您的请求循环必须有一种方法来捕获调用者这样一种方式,当未来最终完成时,呼叫者可以被告知结果
假设您的请求循环收到一个response
回调的请求对象,那么您可以像这样调用longReq
(假设使用longReq
返回{ {1}}):
Future
您将使用该流的最常见方案是HTTP或其他服务器,其中同步def asyncCall(request: Request): Unit = {
longReq(request.data).map( result => request.response(result) )
}
周期的异步等效于Request => Response
,几乎任何现代服务器框架提供(Play,Finatra,Scalatra等)
何时使用Request => Future[Response]
使用Await.result
可能合理的一种情况是,如果你有一堆Await.result
并且愿意在全部完成时阻止(假设使用Future
}返回longReq
):
Future
当然, val futures = allData.map(longReq)) // List[Future[String]]
val combined = Future.sequence(futures) // Future[List[String]]
val responses = Await.result(combined, 10.seconds) // List[String]
是combined
,Future
优于map
并以异步方式处理结果