2011-10-12 3 views
1

Je souhaite envoyer une liste de messages à un acteur, recevoir une réponse immédiatement dans un futur, puis attendre que tous les contrats à terme soient terminés avant de revenir à la méthode d'appel. En lisant les documents akka, je crois que Future.sequence est la voie à suivre, mais je n'ai pas réussi à obtenir le code suivant pour fonctionner correctement. Je reçois cette erreur du compilateur:Utilisation de futurs akka et d'acteurs pour paralléliser une liste

found : akka.dispatch.ActorCompletableFuture 
    required: akka.dispatch.Future[Integer] 
Error occurred in an application involving default arguments. 
      futures += secondary ? GetRandom 
           ^

Je suis sûr que je manque quelque chose évidente mais le code ci-dessous semble être « correcte » par les exemples et l'API docs.

import java.util.Random 
import akka.dispatch.Future 
import akka.actor._ 
import Commands._ 
import collection.mutable.ListBuffer 

object Commands { 
    trait Command 

    case class GetRandom() extends Command 
    case class GenRandomList() extends Command 
} 

class Secondary() extends Actor { 
    val randomGenerator = new Random() 

    override def receive = { 
     case GetRandom() => 
      self reply randomGenerator.nextInt(100) 
    } 
} 

class Primary() extends Actor { 
    private val secondary = Actor.actorOf[Secondary] 

    override def receive = { 

     case GenRandomList() => 

      val futures = new ListBuffer[Future[Integer]] 

      for (i <- 0 until 10) { 
       futures += secondary ? GetRandom 
      } 

      val futureWithList = Future.sequence(futures) 

      futureWithList.map { foo => 
       println("Shouldn't foo be an integer now? " + foo) 
      }.get 
    } 

    override def preStart() = { 
     secondary.start() 
    } 
} 

class Starter extends App { 
    println("Starting") 
    var master = Actor.actorOf(new Primary()).start() 
    master ! GenRandomList() 
} 

Quelle est la bonne façon d'envoyer une série de messages à un acteur, de recevoir un avenir et revenir une fois que tous les contrats à terme ont terminé (le cas échéant stocker les résultats de chaque futur dans une liste et de le retourner).

+0

Quelle version Akka utilisez-vous? –

+0

Akka 1.2 avec Scala 2.9.1. –

Répondre

3
(secondary ? GetRandom).mapTo[Int] 
3

Akka ? renvoie un Future[Any] mais vous avez besoin d'un Future[Int].

Ainsi, vous pouvez définir une liste qui accepte tous les types de contrats à terme:

val futures = new ListBuffer[Future[Any]] 

ou jeté le résultat en tant Int dès qu'il est disponible:

for (i <- 0 until 10) { 
    futures += (secondary ? GetRandom) map { 
    _.asInstanceOf[Int] 
    } 
} 

BTW, pour faire il travail, vous devez changer GetRandom définition:

case object GetRandom extends Command 

une d correspondre avec:

case GetRandom => 
+0

Bonne réponse, merci pour l'aide. J'aimerais pouvoir marquer deux réponses comme réponse acceptée. –

+1

Je recommande: Vector.fill (10) ((secondaire? GetRandom) .mapTo [Int]) –

+0

Merci, j'ai découvert 'mapTo' avec votre réponse. Dans quelle version a-t-il été introduit? – paradigmatic

Questions connexes