Question

la réponse à une de mes questions récente qu'un acteur a traité ses messages un à la fois . Est-ce vrai? Je ne vois rien qui dit explicitement cela (dans Programmer en Scala ), qui contient l'extrait suivant (pp. 593)

  

Si [la méthode réagit ] trouve un message qui peut être traité, [elle] planifiera le traitement de ce message pour une exécution ultérieure et lèvera une exception

(L'accent est le mien). Deux questions liées (et mutuellement exclusives):

  1. En supposant qu'un acteur puisse traiter plusieurs messages simultanément, comment puis-je le forcer à traiter les messages un par un (si c'est ce que je souhaite faire)? (en utilisant receive ?)
  2. En supposant qu'un acteur traite les messages un à un, quelle serait la meilleure implémentation d'un acteur qui pourrait traiter simultanément les messages

edit: faire quelques tests semble confirmer que je me trompe et que les acteurs sont effectivement séquentiels. C'est donc la question n ° 2 à laquelle j'ai besoin de répondre

Était-ce utile?

La solution

Les acteurs traitent un message à la fois. Le modèle classique pour traiter plusieurs messages consiste à avoir un coordonnateur avant acteur pour un groupe d’acteurs consommateurs. Si vous utilisez react, le pool de consommateurs peut être volumineux, mais n'utilisera toujours qu'un petit nombre de threads JVM. Voici un exemple où je crée un pool de 10 consommateurs et un coordinateur à leur tête.

import scala.actors.Actor
import scala.actors.Actor._

case class Request(sender : Actor, payload : String)
case class Ready(sender : Actor)
case class Result(result : String)
case object Stop

def consumer(n : Int) = actor {
  loop {
    react {
      case Ready(sender) => 
        sender ! Ready(self)
      case Request(sender, payload) =>
        println("request to consumer " + n + " with " + payload)
        // some silly computation so the process takes awhile
        val result = ((payload + payload + payload) map {case '0' => 'X'; case '1' => "-"; case c => c}).mkString
        sender ! Result(result)
        println("consumer " + n + " is done processing " + result )
      case Stop => exit
    }
  }
}

// a pool of 10 consumers
val consumers = for (n <- 0 to 10) yield consumer(n)

val coordinator = actor {
  loop {
     react {
        case msg @ Request(sender, payload) =>
           consumers foreach {_ ! Ready(self)}
           react {
              // send the request to the first available consumer
              case Ready(consumer) => consumer ! msg
           }
         case Stop => 
           consumers foreach {_ ! Stop} 
           exit
     }
  }
}

// a little test loop - note that it's not doing anything with the results or telling the coordinator to stop
for (i <- 0 to 1000) coordinator ! Request(self, i.toString)

Ce code teste le consommateur disponible et envoie une demande à ce consommateur. Les solutions de rechange consistent simplement à attribuer aux consommateurs de manière aléatoire ou à utiliser un planificateur à tour de rôle.

Selon ce que vous faites, vous serez peut-être mieux servi avec les Futures de Scala. Par exemple, si vous n'avez pas vraiment besoin d'acteurs, tous les mécanismes ci-dessus peuvent être écrits ainsi:

import scala.actors.Futures._

def transform(payload : String) = {      
  val result = ((payload + payload + payload) map {case '0' => 'X'; case '1' => "-"; case c => c}).mkString
  println("transformed " + payload + " to " + result )
  result
}

val results = for (i <- 0 to 1000) yield future(transform(i.toString))

Autres conseils

Je pense que la réponse est qu'un acteur ne peut pas gérer les messages de manière synchrone. Si vous avez un Acteur qui doit écouter des messages dans lesquels ces messages peuvent être traités de manière asynchrone , il pourrait alors être écrit de la manière suivante:

val actor_ = actor {

  loop {
    react {
      case msg =>
        //create a new actor to execute the work. The framework can then 
        //manage the resources effectively
        actor {
          //do work here
        }
      }
    }
  }

Si vous voulez faire plusieurs choses, vous devriez utiliser plusieurs acteurs. La raison d’utiliser des acteurs est de diviser le travail en plusieurs processus indépendants.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top