我们在Scala框架应用程序中使用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秒,搜索总是在不到200 qa的时间内执行)。这在使用scala全局执行上下文以及使用Play默认执行上下文时也会发生。
这里是否存在某种意外的交互,因为java未来被包装在scala未来中?我原以为actionGet在doSearch结束时对java未来的呼吁会阻止这两个未来相互干扰,但显然情况并非如此。
发布于 2014-03-17 21:15:41
我以为堵住是邪恶的。邪恶!
在本例中,Await.result将阻塞当前线程,因为它正在等待结果。
Await将调用包装在blocking中,试图通知线程池,它可能希望增长一些线程以保持其所需的并行性并避免死锁。
如果当前线程不是Scala BlockContext,则只会遇到阻塞。
不管你的精确配置是什么,想必你是在阻塞线程的时候抓住一个线程,而你正在为搜索而奔波的声音想要运行一些东西,而不能运行,因为池已经耗尽了。
相关的是是什么池产生了当前线程:如果您需要从当前池中使用更多的线程,并且它已经耗尽,那么在不同的池上是否存在中间的未来并不重要。
当然,这只是猜测。
更有意义的是,有一个单独的未来,从这两个搜索获得值,并有一个超时。
但是,如果你最终得到了多个期货,那么使用Future.sequence并等待它是有意义的。
https://stackoverflow.com/questions/22457573
复制相似问题