Utilisez les Futures dans Scala 2.10. Il s'agissait d'un travail conjoint entre l'équipe Scala, l'équipe Akka et Twitter pour parvenir à une API et une implémentation futures plus standardisées pour une utilisation dans tous les frameworks. Nous venons de publier un guide à : http://docs.scala-lang.org/overviews/core/futures.html
En plus d'être complètement non bloquants (par défaut, bien que nous fournissions la possibilité d'effectuer des opérations bloquantes gérées) et composables, les futures de Scala 2.10 sont livrés avec un pool de threads implicite pour exécuter vos tâches, ainsi que quelques utilitaires pour gérer les délais.
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)
Ci-dessus, nous importons d'abord un certain nombre de choses :
-
future
: API pour créer un avenir.
-
blocking
: API pour le blocage géré.
-
Future
: Objet compagnon du futur qui contient un certain nombre de méthodes utiles pour collections d'avenirs.
-
Await
Objet singleton utilisé pour bloquer un futur (en transférant son résultat au thread actuel).
-
ExecutionContext.Implicits.global
le pool de threads global par défaut, un pool ForkJoin.
-
duration._
: des utilitaires pour gérer les durées des interruptions de service.
imagesFuts
reste en grande partie la même que ce que vous avez fait à l'origine - la seule différence ici est que nous utilisons le blocage géré -. blocking
. Il informe le pool de threads que le bloc de code que vous lui transmettez contient des opérations longues ou bloquantes. Cela permet au pool de créer temporairement de nouveaux travailleurs pour s'assurer que tous les travailleurs ne sont jamais bloqués. Ceci est fait pour éviter la famine (blocage du pool de threads) dans les applications bloquantes. Notez que le pool de threads sait également quand le code d'un bloc bloquant géré est terminé - il supprimera donc le thread ouvrier disponible à ce moment-là, ce qui signifie que le pool sera ramené à sa taille prévue.
(Si vous voulez absolument empêcher la création de threads supplémentaires, vous devez utiliser une bibliothèque AsyncIO, comme la bibliothèque NIO de Java).
Ensuite, nous utilisons les méthodes de collecte de l'objet compagnon Future pour convertir les données de la base de données en données de la base de données. imagesFuts
de List[Future[...]]
à un Future[List[...]]
.
El Await
est la façon dont nous pouvons nous assurer que display
est exécuté sur le thread appelant-- Await.result
force simplement le thread actuel à attendre que le futur qui lui est transmis soit terminé. (Ceci utilise le blocage géré en interne).