阻止未来有什么意义吗?

时间:2015-10-22 19:06:41

标签: scala concurrency future

假设我有一个提供许多请求的应用程序。其中一个请求需要一段时间才能完成。我有以下代码:

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的同时并行处理其他请求?

1 个答案:

答案 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] combinedFuture优于map并以异步方式处理结果