私はJavaのバックグラウンドから来ているScalaの未来を理解しようとしています:あなたが書くことができることを理解しています:
val f = Future { ... }
次に、2 つの質問があります。
- この未来はどのように予定されていますか?自動的?
- どのスケジューラーを使用しますか? Java では、スレッド プールなどのエグゼキュータを使用します。
scheduledFuture
さらに、特定の時間遅延後に実行される をどのように達成できますか? ありがとう
私はJavaのバックグラウンドから来ているScalaの未来を理解しようとしています:あなたが書くことができることを理解しています:
val f = Future { ... }
次に、2 つの質問があります。
scheduledFuture
さらに、特定の時間遅延後に実行される をどのように達成できますか? ありがとう
このブロックは(Maciej のことはご存じだと思いますが) をFuture { ... }
呼び出すための構文糖衣であり、コードのブロックを最初の引数として渡します。Future.apply
このメソッドのドキュメントを見ると、それが暗黙的であることがわかりますExecutionContext
- そして、それがどのように実行されるかを決定するのはこのコンテキストです。したがって、2番目の質問に答えるために、将来は暗黙のスコープにある ExecutionContext によって実行されます(もちろん、これがあいまいな場合はコンパイル時エラーです)。
多くの場合、これは の 1 つになりますimport ExecutionContext.Implicits.global
。これはシステム プロパティで調整できますが、デフォルトではThreadPoolExecutor
プロセッサ コアごとに 1 つのスレッドを使用します。
ただし、スケジューリングは別の問題です。一部のユースケースではExecutionContext
、実行前に常に同じ遅延を適用する独自のものを提供できます。しかし、呼び出しサイトから遅延を制御できるようにしたい場合は、もちろん、Future.apply
これをスケジュールする方法を伝えるパラメーターがないため、使用できません。この場合、スケジュールされたエグゼキューターにタスクを直接送信することをお勧めします。
Andrzejの答えは、あなたの質問のほとんどをすでにカバーしています。言及する価値があるのは、Scala の「デフォルト」の暗黙的な実行コンテキスト ( import scala.concurrent.ExecutionContext.Implicits._
) は文字通りでjava.util.concurrent.Executor
あり、ExecutionContext の概念全体は非常に薄いラッパーですが、Java のエグゼキューター フレームワークと密接に連携していることです。
マウリシオが指摘するように、スケジュールされた先物に似たものを達成するには、プロミスとサードパーティのスケジューリングメカニズムを使用する必要があります。
Scala 2.10 のフューチャーにこの共通のメカニズムが組み込まれていないのは残念ですが、致命的なことではありません。
promise は、非同期計算のハンドルです。ExecutionContext
を呼び出して作成します (スコープ内であると仮定) val p = Promise[Int]()
。整数を約束しただけです。クライアントは、単にScala のフューチャである を
呼び出すだけで、満たされたプロミスに依存するフューチャを取得できます。
約束を果たすことは単に を呼び出すことであり、その時点で未来が完成します。 p.future
p.successful(3)
Play 2.x は、promise と単純な古い Java 1.4 タイマーを使用してスケジューリングを解決します。
これは、ソースへのlinkrot -proofリンクです。
ここでソースも見てみましょう。
object Promise {
private val timer = new java.util.Timer()
def timeout[A](message: => A, duration: Long, unit: TimeUnit = TimeUnit.MILLISECONDS)
(implicit ec: ExecutionContext): Future[A] = {
val p = Promise[A]()
timer.schedule(new java.util.TimerTask {
def run() {
p.completeWith(Future(message)(ec))
}
}, unit.toMillis(duration))
p.future
}
}
これは次のように使用できます。
val future3 = Promise.timeout(3, 10000) // will complete after 10 seconds
Thread.sleep(10000)
これは、スレッドをブロックしてコンテキスト スイッチを強制するコードにa をプラグインするよりもはるかに優れていることに注意してください。
また、この例で注目に値するのはval p = Promise...
、関数の最初とp.future
最後にある です。これは、promise を操作する際の一般的なパターンです。この関数がクライアントに何らかの約束をし、それを実行するために非同期計算を開始することを意味すると解釈してください。
Scala promise の詳細については、こちらを参照してください。ではなく、パッケージ オブジェクトの小文字のfuture
メソッドを使用していることに注意してください。前者は単に後者に委任します。個人的には小文字の方が好きです。concurrent
Future.apply
future