31

Java ライブラリの小さなスカラ ラッパーを作成中です。

Java ライブラリには、2 つのメソッドを公開するオブジェクト QueryExecutor があります。

  • 実行 (クエリ): 結果
  • asyncExecute(クエリ): ListenableFuture[結果]

このコンテキストでの ListenableFuture は、guava ライブラリのものです。

Scala ラッパーが Java オブジェクトではなく Future[Result] を返すようにしたいのですが、それを実装する最善の方法がわかりません。私が思いついた2つの解決策は次のとおりです。

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 を返しますが、execute の呼び出しが応答を待っている間もスレッドをブロックし、2 番目のものは実際には非ブロックであるように見えます。各方法の長所/短所について何かコメントはありますか?

4

2 に答える 2

47

2 番目のオプションが最適です。すべてを非同期に保ちます。しかし... 1つ改善して、ソリューションを再利用可能なパターンに抽象化できます。

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
于 2013-10-22T21:23:45.607 に答える
3

別の、少し短い解決策:

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())), e)
    p.future
  }
}
于 2018-09-24T07:23:35.687 に答える