ListenableFuture to scala Future

时间:2013-08-02 21:46:16

标签: scala future

我正在围绕java库编写一个小的scala包装器。

java库有一个QueryExecutor对象,它暴露了两种方法:

  • 执行(查询):结果
  • asyncExecute(query):ListenableFuture [Result]

此上下文中的ListenableFuture来自番石榴库。

我希望我的scala包装器返回Future [Result]而不是java对象,但我不确定实现它的最佳方法是什么。以下是我提出的两个解决方案:

future {
  executor.execute(query)
}

val p = promise[Result]
val guavaFuture = executor.asyncExecute(query)

Futures.addCallback(guavaFuture, new FutureCallback[Result] {
  def onFailure(t: Throwable) {
    p.failure(t)
  }

  def onSuccess(result: Result) {
    p.success(result)
  }
})

p.future

我想知道哪种方法最好。我的直觉是第一个,当返回一个Future时,仍然会阻塞一个线程,而执行调用等待响应,第二个看起来应该是非阻塞。对每种方法的利弊有何评论?

2 个答案:

答案 0 :(得分:45)

第二个选项是最好的,它可以保持所有异步。但是......你可以做得更好,并将解决方案抽象为可重用的模式:

implicit class RichListenableFuture[T](lf: ListenableFuture[T]) {
  def asScala: Future[T] = {
    val p = Promise[T]()
    Futures.addCallback(lf, new FutureCallback[T] {
      def onFailure(t: Throwable): Unit = p failure t
      def onSuccess(result: T): Unit    = p success result
    })
    p.future
  }    
}

然后您可以简单地致电:

executor.asyncExecute(query).asScala

答案 1 :(得分:1)

另一个更短的解决方案:

implicit class ListenableFutureDecorator[T](val f: ListenableFuture[T]) extends AnyVal {
  def asScala(implicit e: Executor): Future[T] = {
    val p = Promise[T]()
    f.addListener(() => p.complete(Try(f.get())), implicitly[Executor])
    p.future
  }
}