Kann Scala Schauspieler verarbeiten gleichzeitig mehrere Nachrichten?
-
06-07-2019 - |
Frage
Die Antwort eine aktuelle Frage von mir angezeigt dass ein Schauspieler seine Nachrichten verarbeitet einen nach dem anderen . Ist das wahr? Ich sehe nichts, was ausdrücklich sagt, dass (in Programmierung in Scala ), die den folgenden Ausschnitt enthält (pp. 593)
Wenn [die
react
Methode] eine Nachricht findet, die behandelt werden können, [es] wird plant den Umgang mit dieser Meldung für die spätere Ausführung und eine Ausnahme auslösen
(Schwerpunkt meiner eigenen). Zwei verwandte (und sich gegenseitig ausschließende) Fragen:
- Schauspieler Unter der Annahme, simulatenously mehrere Nachrichten verarbeiten kann, wie kann ich einen Schauspieler zwingen Nachrichten: 1 zu einem Zeitpunkt, zu verarbeiten (wenn das ist, was ich tun wollen)? (Mit
receive
?) - Schauspieler Unter der Annahme verarbeitet Nachrichten einen nach dem anderen, wie würde ich einen Schauspieler am besten implementieren, die in der Tat könnte Prozessmeldungen gleichzeitig
edit: ein wenig getestet tun scheint out zu tragen, dass ich falsch liege und dass die Akteure sind in der Tat sequentiell. Es ist also Frage # 2, die ich beantworten muß
Lösung
Schauspieler verarbeiten eine Nachricht zu einer Zeit. Das klassische Muster mehr Nachrichten zu verarbeiten, ist einen Koordinator Schauspieler Front für einen Pool von Verbrauchern Akteure zu haben. Wenn Sie reagieren verwenden dann kann der Verbraucher Pool groß sein, sondern nur noch eine geringe Anzahl von JVM-Threads verwenden. Hier ist ein Beispiel, wo ich einen Pool von 10 Verbrauchern und einem Koordinator nach vorne für sie erstellen.
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)
Dieser Code prüft, um zu sehen, welche Verbraucher verfügbar ist und sendet eine Anfrage an diesen Verbraucher. Alternativen sind nur zufällig an den Verbraucher zuweisen oder einen Round-Robin-Scheduler zu verwenden.
Je nachdem, was Sie tun, werden Sie vielleicht besser mit Scala Futures serviert. Wenn Sie zum Beispiel nicht wirklich Akteure müssen dann alle der oben genannten Maschinen könnten als
geschriebenimport 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))
Andere Tipps
Ich denke, die Antwort ist, dass ein Actor
keine Nachrichten aynchronously verarbeiten kann. Wenn Sie eine Actor
haben, die Nachrichten hören sollte, wo diese Nachrichten können asynchron behandelt werden , dann könnte es wie folgt geschrieben werden:
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
}
}
}
}
Wenn Sie mehrere Dinge tun wollen, dann sollten Sie mit mehreren Akteuren werden. Der ganze Grund Akteure zu nutzen, um die Arbeit auf mehrere voneinander unabhängige Prozesse aufzuteilen.