いくつかのURLからダウンロードする画像の(潜在的に大きな)リストを取得しているとしましょう。私はScalaを使用しているので、私がすることは次のとおりです。
import scala.actors.Futures._
// Retrieve URLs from somewhere
val urls: List[String] = ...
// Download image (blocking operation)
val fimages: List[Future[...]] = urls.map (url => future { download url })
// Do something (display) when complete
fimages.foreach (_.foreach (display _))
私はScalaに少し慣れていないので、これはまだ魔法のように見えます。
display _
)メインスレッドで実行されます。そうでない場合、どうすればそれを確認できますか?アドバイスをしてくれてありがとう!
Scalaで先物を使用する2.10これらは、Scalaチーム、Akkaチーム、Twitterの共同作業であり、フレームワーク全体で使用するためのより標準化された将来のAPIと実装に到達しました。ガイドを公開しました: http://docs.scala-lang.org/overviews/core/futures.html
Scalaの2.10先物には、完全に非ブロッキング(デフォルトでは、マネージドブロッキング操作を行う機能はありますが)および構成可能であることに加えて、タスクを実行するための暗黙的なスレッドプールと、タイムアウトを管理するためのユーティリティが付属しています。
import scala.concurrent.{future, blocking, Future, Await, ExecutionContext.Implicits.global}
import scala.concurrent.duration._
// Retrieve URLs from somewhere
val urls: List[String] = ...
// Download image (blocking operation)
val imagesFuts: List[Future[...]] = urls.map {
url => future { blocking { download url } }
}
// Do something (display) when complete
val futImages: Future[List[...]] = Future.sequence(imagesFuts)
Await.result(futImages, 10 seconds).foreach(display)
上記では、最初にいくつかのものをインポートします。
future
:未来を作成するためのAPI。blocking
:マネージドブロッキング用のAPI。Future
:futuresのコレクションに役立つメソッドを多数含むFutureコンパニオンオブジェクト。Await
:将来のブロック(結果を現在のスレッドに転送)に使用されるシングルトンオブジェクト。ExecutionContext.Implicits.global
:デフォルトのグローバルスレッドプールであるForkJoinプール。duration._
:タイムアウトの期間を管理するためのユーティリティ。imagesFuts
は元の状態とほぼ同じままです。ここでの唯一の違いは、マネージドブロッキングを使用することですblocking
。スレッドプールに、渡したコードブロックに長時間実行またはブロック操作が含まれていることを通知します。これにより、プールは一時的に新しいワーカーを生成し、すべてのワーカーがブロックされないようにします。これは、ブロッキングアプリケーションでの飢star(スレッドプールのロックアップ)を防ぐために行われます。スレッドプールは、マネージドブロックブロックのコードがいつ完了するかを知っているため、その時点でスペアワーカースレッドを削除することに注意してください。つまり、プールは予想サイズまで縮小します。
(追加のスレッドが作成されないようにする場合は、JavaのNIOライブラリなどのAsyncIOライブラリを使用する必要があります。)
次に、Futureコンパニオンオブジェクトのコレクションメソッドを使用して、imagesFuts
をList[Future[...]]
からFuture[List[...]]
に変換します。
Await
オブジェクトは、display
が呼び出しスレッドで実行されることを確認する方法です。Await.result
は、渡された未来が完了するまで現在のスレッドを単に待機させるだけです。 (これは内部で管理されたブロッキングを使用します。)
val all = Future.traverse(urls){ url =>
val f = future(download url) /*(downloadContext)*/
f.onComplete(display)(displayContext)
f
}
Await.result(all, ...)
はい、私には問題ないようですが、より強力な Twitter-util または Akka Future APIを調査することをお勧めします(Scala 2.10にはこのスタイルの新しいFutureライブラリがあります)。
スレッドプールを使用します。
いいえ、できません。このためには、GUIツールキットの標準メカニズムを使用する必要があります(SwingUtilities.invokeLater
スイングまたはDisplay.asyncExec
(SWTの場合)。例えば。
fimages.foreach (_.foreach(im => SwingUtilities.invokeLater(new Runnable { display im })))