【问题标题】:Scala and Java futures apparently having unexpected interactionsScala 和 Java 的未来显然有意想不到的交互
【发布时间】:2014-04-22 20:20:30
【问题描述】:

我们在 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 秒,其中搜索总是在不到 200 毫秒内执行)。使用 scala 全局执行上下文以及使用 Play 默认执行上下文时也会发生这种情况。

由于将 java 未来包装在 scala 未来中,这里是否会发生某种意外的交互?我原以为在doSearch 结尾处对java 未来的actionGet 调用会阻止这两个未来相互干扰,但显然情况可能并非如此。

【问题讨论】:

  • 可能做不到,但是如果您可以编写一个其他人可以运行的测试用例并重新创建问题,它可能有助于调试。
  • @JohnVint 我一直在尝试这样做,但不幸的是,低悬的果实 (do while(i &lt; 100) { i = i + 1; val f1 = Future(doSearch(...)); val f2 = Future(doSearch(...)); Await(f1, defaultDuration); Await(f2, defaultDuration)}) 并没有引发问题;我会继续玩这个,这样我就可以一直得到错误

标签: java multithreading scala concurrency scala-java-interop


【解决方案1】:

我认为在某个地方建立了阻塞是邪恶的。邪恶!

在这种情况下,Await.result 将阻塞当前线程,因为它正在等待结果。

如果当前线程不是 Scala BlockContext,那么你只会得到阻塞。

无论您的精确配置是什么,大概您在阻塞时保持在一个线程上,而您正在运行的搜索 thunk 想要运行某些东西而不能运行,因为池已用尽。

相关的是哪个池产生了当前线程:中间的 Future 是否在不同的池上并不重要,如果你需要使用当前池中的更多线程并且它已经耗尽。

p>

当然,这只是猜测。

拥有一个从两个搜索中获取值的未来更有意义,并且有超时。

但如果您最终拥有多个 Future,则使用 Future.sequence 并等待它是有意义的。

【讨论】:

    猜你喜欢
    • 2013-04-11
    • 1970-01-01
    • 2012-12-11
    • 2013-03-25
    • 2016-02-06
    • 2016-10-12
    • 1970-01-01
    • 2016-12-17
    • 2022-01-05
    相关资源
    最近更新 更多