2013-08-02 14 views
26

私は、Javaライブラリの周りに小さなスケーララッパーを書く過程にあります。ListenableFuture to scala Future

Javaライブラリは、2つの方法露光対象QueryExecutor有する:

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

ListenableFutureこのコンテキストにありますグアバライブラリのもの。

私はスカラーラッパーにJavaオブジェクトの代わりにFuture [Result]を返すようにしたいが、それを実装する最良の方法は何か分からない。私が最適な方法を疑問に思って

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 

:ここに私が思い付いた2つの溶液です。私の直感は、実行する呼び出しが応答を待つ間、未来を返す最初のスレッドはスレッドをブロックし、2番目のスレッドは実際にはブロックされないように見えるということです。各方法の賛否両論に対するコメント?

+2

あなたは4つのプロセッサを持っていると仮定します。この場合、デフォルトの 'ExecutionContext'は4人の作業者で構成されます。 'future {executor.execute(query)}'はそれぞれ1人のワーカーをブロックするので、4つの "future"はあなたのプログラムを完全にブロックします。操作をブロックするために追加の 'ExecutionContext'を作成できますが、オーバーヘッドがあります。 – senia

+0

おかげさまで@senia、それは私が思ったことです。最初のコードは呼び出し元の観点からは非同期ですが、ExecutionContextのスレッドをブロックしますが、2番目のコードは実際にはブロックされません(asyncExecuteが非ブロックIOを使用すると仮定します)。私はこれが非常に基本的な質問だと思っていますが、私は約束にはあまり慣れていません。 – vptheron

+1

これは、類似した(または同じ可能性もある)要求で役に立ちます:https://github.com/eigengo/activator-akka-cassandra/blob/master/src/main/scala/core/cassandra.scala – Gavin

答えて

37

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 
+1

素晴らしい解決策。私のListenableFutureインターフェイスコードがこの暗黙的なコードとどれくらい綺麗なのか信じられません –

+2

とてもいいです。 'Promise [T]'を使ってもっと抽象的になるかもしれません – raam86

+0

toPromiseが実際に未来を返すことを助けることはできませんが、指摘してください。 ;)そうでなければ、それを愛する! –

関連する問題