用于java.util.concurrent.Future的scala.concurrent.Future包装器

Mar*_*ill 21 java concurrency scala future playframework-2.1

我正在使用Play Framework 2.1.1和一个生成java.util.concurrent.Future结果的外部Java库.我正在使用scala future而不是Akka,我认为这是Play 2.1的正确选择.如何在保持代码无阻塞的同时将java.util.concurrent.Future包装到scala.concurrent.Future中?

def geConnection() : Connection = {
  // blocking with get
  connectionPool.getConnectionAsync().get(30000, TimeUnit.MILLISECONDS)
}
Run Code Online (Sandbox Code Playgroud)

上面的代码返回一个连接,但使用了get,所以它变成了阻塞

def getConnectionFuture() : Future[Connection] = {
  future {
    // how to remove blocking get and return a scala future?
    connectionPool.getConnectionAsync().get(30000, TimeUnit.MILLISECONDS)
  }
}
Run Code Online (Sandbox Code Playgroud)

理想情况下,我想要一个scala函数,它返回连接作为未来,如上面的代码,但没有通过get阻止代码.我需要在函数中添加什么才能使其无阻塞.

任何指针都会很棒.

sen*_*nia 21

import java.util.concurrent.{Future => JFuture}
import scala.concurrent.{Future => SFuture}
Run Code Online (Sandbox Code Playgroud)

你可以不换JFutureSFuture不阻塞,因为在回调SFuture(onComplete),而且只堵getJFuture.

你所能做的就是创建额外的线程并用它来阻止它get,然后完成Promise结果get.

val jfuture: JFuture[T] = ???
val promise = Promise[T]()
new Thread(new Runnable { def run() { promise.complete(Try{ jfuture.get }) }}).start
val future = promise.future
Run Code Online (Sandbox Code Playgroud)

你可以检查isDone无限循环,但我不认为它比阻塞更好.

  • @PetrPudlák:它会阻止线程拉动中的线程.如果您为这样的期货配置了`ExecutionContext`,那很好,但默认的`ExecutionContext`包含[尽可能多](https://github.com/scala/scala/blob/v2.10.2/src/library/scala/concurrent /impl/ExecutionContextImpl.scala#L68)线程,因为你有处理器. (4认同)
  • 同意.遗憾的是,Java未来不支持回调的某种完成侦听器/观察器 (3认同)

Dr.*_*ibo 5

Future {
  blocking {
    jfuture.get
  }
}
Run Code Online (Sandbox Code Playgroud)

这使ExecutionContext知道您正在执行的操作将被阻塞,从而有机会分配更多的线程。如果不包括,blocking { }则可能会用完线程。

  • 而且,如果您执行“阻塞”操作,那么最终可能会在高负载下产生数万个线程。小心-“阻止”不是魔术! (3认同)