2017-12-04 8 views
1

それを行うことが可能である:スケーラを持つことは可能ですか?Futureは、Java CompletableFutureのように、同じスレッドでマッピングアクションを実行しますか? Javaでは

CompletableFuture<Integer> e = new CompletableFuture<Integer>(); 
e = e.thenApply(x -> x * 2); 
e.complete(12); 

このシナリオでthenApply内の関数がe.completeを呼び出しているスレッドで実行されます私は将来のために、すべての操作機能に気づいスカラ座でthenApply

を見ます引数としてExecutionContextを持っているので、私はmap(それはthenAppApplyと同じです)が別のタスクを実行コンテキストに送ると仮定します。

非同期メソッド以外でJava CompletableFutureの同じ動作を取得するにはどうすればよいですか?

+0

perfの問題が気付かない限り、なぜ心配していますか? (時期尚早な最適化...) – cchantep

答えて

1

はい、これは可能です。実際、scalaのExecutionContextは、Javaのスレッドプールとは対照的に、コードが実行されている場所を要約しており、特定のスレッドプールのスレッドでスケジューリングする必要はありません。その代わりに、現在のスレッドである可能性もあります。これは通常、不正実行コンテキストと呼ばれます。

例えばプレイフレームワークは1を定義しています。https://github.com/playframework/playframework/blob/38abd1ca6d17237950c82b1483057c5c39929cb4/framework/src/play-streams/src/main/scala/play/api/libs/streams/Execution.scala#L31

しかし、これを実装する前に、あなたは本当にあなたが何をやっている知っているとあなたが本当にこれを必要とすることを確認する必要があります。実際には、プレイフレームワークはそれを公開することを決断しました。

だから、トランポリンは広く知られておらず、パフォーマンス上の利点につながりませんユーザーのために、閉じる。

出典:https://github.com/playframework/playframework/issues/6390

同様の議論は、議論がScalaの標準ライブラリに1を追加するかどうかをしたリストを、メーリングリストのscala-interalsに起こりました。

我々はそれが極めて容易 wreakが同期実装ために有することができるので、一般的なものとして、それを露光に躊躇している:最後に、予約が類似していました。

出典:https://monix.io/api/3.0/

+0

私は、「ユーザーにとってパフォーマンス上の利点につながりません」という主張を理解していません。私はそれがより効率的になる多くのシナリオを考えることができます。はい、人が慎重でないとデッドロックにつながる可能性がありますが、これは高度な機能といえます。 .NETとjavaの両方は、パフォーマンス上の理由からこれを行います。 – Voo

+0

私は彼が何を意味したかは、あなたが本当にあなたのことを知っている必要があるということでした。そうでなければ、利益は価格の価値がないかもしれません。 – rethab

0

感謝した後、@rethab:https://groups.google.com/forum/#!msg/scala-internals/QgtKugpqUlk/llVXveEuFAAJ

はまた、そのようなmonixなどパフォーマンスセンシティブ/並行コードを書いている場合に役立つかもしれない代替の実装が存在することに注意してくださいあなたのポインタを見て、ExecutionContextのデフォルトの実装を見て、私は非常に単純な解決策を見つけました:

object MyExCont extends ExecutionContext { 
    override def execute(runnable: Runnable): Unit = runnable.run() 

    override def reportFailure(cause: Throwable): Unit = cause.printStackTrace() 
    } 


    def main(args: Array[String]): Unit = { 
    val p = Promise[String]() 
    val e = p.future 

    val t = new Thread(()=>{ 
     LOGGER.info("Completing") 
     p.complete(Try { 
     "hello" 
     }) 
    }) 

    val f = e.map(x => { 
     LOGGER.info("Adding...") 
     x + ";" 
    }, MyExCon) 

    Thread.sleep(10) 
    t.start() 
    LOGGER.info(Await.result(f, Duration.Inf)) 
    } 

これは

  1. 未来はe.mapの時間(...)で完了していない場合先物である場合には、Promise.completeが呼び出されたスレッドがマッピング操作
  2. を実行します:どちらかで結果e.map(...)の時に完了すると、e。マップが実行され、作業が実行されます。
関連する問題