2017-10-10 3 views
0

私はScalaでRedisを使用します。 Redisタスクはfutureなので、私は未来(スレッド)を勉強しなければなりません。Scalaでの違いは何ですか?Await、Thread.sleep、および理解のためですか?

futureが停止するまで待つ方法がたくさん見つかりました。私は違いが何であるか分からない。 Await,Thread.sleepforの間の相違点は何ですか?

val redisResult1 = redis.set(objectId, value) 
    Await.ready(redisResult1, Duration.Inf) 

    val redisResult2 = redis.set(objectId, value) 
    for { 
    _ <- redisResult2 
    } yield { 
    "end" 
    } 

    val redisResult3 = redis.set(objectId, value) 
    while(redisResult3.isCompleted) Thread.sleep(10) 
+0

理想的には、待つ(できるだけ遠ざけてください)とチェーンの先物(それを 'for 'のように)を避けるのが理想的です。 – Thilo

+0

whileループでポーリングする場合は、while(!isCompleted)にする必要があります。しかし、この正確な目的のために作られた 'Await.ready'を使う方が良いでしょう。 – Thilo

+0

hwanの下には2つの一見良い答えがあります。 – halfer

答えて

1

これで、秒の例から始めましょう。 次のコードスニペットを考えてみましょう:

import scala.concurrent.Future 
import scala.concurrent.ExecutionContext.Implicits.global 

object Test2{ 
    def main(args:Array[String]):Unit={ 
    val f = Future{Thread.sleep(5000); "i'm done"} 
    val r = for{ 
     _ <- f 
    } yield "completed" 
    println(r) 
    } 
} 

は、それが印刷されるかと思いますか?それはとても未来が完了するのをここであなたが待っていない実際には、あなたは単に最初の将来の結果をマッピングし、最初の1が完了した後に完了しますその他の将来としてそれを返す

Future(<not completed>) 

Process finished with exit code 0 

を印刷します。あなたが見ているように、プログラムは結果としての未来が完了し、ちょうど正常に終了するまで待たない。先物に関する理解は、それらのマッピングとフラットマッピングのための糖構文です。

Await.resultAwait.readyは、実際には未来が完了するまで(またはタイムアウトするまで)実際に待機します。しかし、彼らはブロック方法でそれを行うので、あなたがこれらのメソッドを使用するスレッドはブロックされます。これは必ずしも悪くないとは限りません。例えば。小さなテストプログラムや、コンソールにあなたの将来の計算の結果を最終的に出したいREPLセッションや、結果を待つ必要のあるテストやテストが待っている間に何もしないテストなどでは、

このような小さなプログラムの結果を確認する別の方法は、scala.io.StdIn.readLine()を使用して、メインスレッドがハングして終了しないようにすることです。このことを示し、以下を考慮し、また、将来の完了を待つために1つの以上の追加の方法を提供します:

object Test2{ 
    def main(args:Array[String]):Unit={ 
    val f = Future{Thread.sleep(5000); "i'm done"} 
    f foreach (println(_)) 

    scala.io.StdIn.readLine() 
    } 

} 

実行して、あなたはそのプログラムが終了していないでしょう、そして未来と出口の結果を出力しますENTERキーを押した後でなければなりません。

foreach今後、onCompleteリスナーを追加するためのショートカットです。かなり便利なもの。

については、未来が完了しているかどうかを継続的にチェックしています - 私はおそらく、メインスレッドをビジーに保ち、効率的に実装されたAwait.resultよりもアイドル状態のCPUパワーを無駄にするので最悪の方法です。他のものと同様にブロックすることは効率的で非効率的でもあります。

未来のすべてのものを理解するには、未来の実際の実行が、それを開始した同じスレッドではなく、実際に実行されることを明確に理解する必要があります。すべての例では、メインスレッドで未来を定義しましたが、インポートされたscala.concurrent.ExecutionContext.Implicits.global実行コンテキストのスレッドの1つで実行されました。

1

慣用的なアプローチは、結果をブロックしないことです。代わりに、地図/を使ってFuturesを連鎖させ、そのような理解とそのようなことを行うべきです。

理解のためのAは、フラットマップ、マップ、およびwithFiltersの文法上の砂糖です。使用方法によって異なります。

これは可能な限り非ブロックであるだけでなく、「ハッピーパス」をコーディングし、できるだけ遅くまで障害を処理することはできません。

Playのような多くのフレームワークでは、未来がブロックされず、Futuresを呼び出し元に返すことができ、フレームワークがそれを処理します。

あなたが未来をアンラップ処理する必要がない場合は、おそらくこのようなものを学んでかなり良いチュートリアルのThe Neophytes Guide to ScalaをチェックonComplete

を使用することにしたいです。

関連する問題