[英]Scala and Java futures apparently having unexpected interactions
我们在Scala Play Framework应用程序中使用Elasticsearch 0.90.7,其中“doSearch”方法的结尾如下所示:
def doSearch(...) = {
...
val actionRequessBuilder: ActionRequestBuilder // constructed earlier in the method
val executedFuture: ListenableActionFuture<Response> = actionRequestBuilder.execute
return executedFuture.actionGet
}
其中ListenableActionFuture
扩展了java.util.concurrent.Future
,而ListenableActionFuture#actionGet
与Future#get
基本相同
当我们按顺序执行搜索时,这一切都正常,但是当我们尝试并行执行多个搜索时:
val search1 = scala.concurrent.Future(doSearch(...))
val search2 = scala.concurrent.Future(doSearch(...))
return Await.result(search1, defaultDuration) -> Await.result(search2, defaultDuration))
我们有时(不到1%或2%的时间)在我们的scala期货上获得意外超时,即使在qa期间使用极长的超时(5秒,搜索总是在不到200ms内执行)。 使用scala全局执行上下文以及使用Play默认执行上下文时也会发生这种情况。
由于Java未来包含在scala未来中,是否存在某种意外的交互? 我actionGet
以为在doSearch
结束时对java未来的actionGet
调用会阻止这两个期货相互干扰,但显然可能并非如此。
我认为它建立在某个地方,阻挡是邪恶的。 邪恶!
在这种情况下, Await.result
将阻塞当前线程,因为它正在等待结果。
Await
在blocking
包装调用,试图通知线程池它可能希望增长一些线程以维持其所需的并行性并避免死锁。
如果当前线程不是Scala BlockContext
,那么你BlockContext
受到阻塞。
无论你的精确配置是什么,大概是你在被阻止时保持一个线程,而你正在运行搜索的thunk想要运行某些东西而不能因为池已经用完了。
什么是相关的是什么池产生了当前的线程:中间的Future是否在不同的池上是无关紧要的,如果在底部,你需要使用当前池中的更多线程并且它已经耗尽。
当然,这只是猜测。
如果有一个单一的未来从两次搜索中获取值,则会更加有意义。
但是如果你结束了多个Futures,那么使用Future.sequence
并等待它就有意义了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.