これで、秒の例から始めましょう。 次のコードスニペットを考えてみましょう:
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.result
とAwait.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つで実行されました。
理想的には、待つ(できるだけ遠ざけてください)とチェーンの先物(それを 'for 'のように)を避けるのが理想的です。 – Thilo
whileループでポーリングする場合は、while(!isCompleted)にする必要があります。しかし、この正確な目的のために作られた 'Await.ready'を使う方が良いでしょう。 – Thilo
hwanの下には2つの一見良い答えがあります。 – halfer