Der einfachste Weg, Leerlaufverarbeitung in einem Scala Schauspieler zu tun?
Frage
Ich habe einen scala Schauspieler, der etwas Arbeit tut, wenn ein Kunde sie anfordert. Wenn, und nur dann, wenn kein Client aktiv ist, würde ich die Schauspieler gerne einige Hintergrundverarbeitung zu tun.
Was ist der einfachste Weg, dies zu tun? Ich kann mich zwei Ansätze:
-
Spawn ein neuer Thread, dass die Zeiten und in regelmäßigen Abständen die Schauspieler aufwacht. Ein geradlinig Ansatz, aber ich würde einen anderen Thread zu vermeiden wie das Erstellen (den zusätzlichen Code zu vermeiden, Komplexität und Overhead).
-
Die Schauspieler-Klasse hat eine reactWithin Methode, die sich von dem Schauspieler selbst zu Zeit verwendet werden könnten. Aber die Dokumentation sagt das Verfahren nicht zurück. Also, ich bin nicht sicher, wie es zu benutzen.
Bearbeiten; eine Klarstellung:
Nehmen wir an, die Hintergrundaufgabe in kleinere Einheiten werden abgebaut, die unabhängig voneinander bearbeitet werden können.
Lösung
Ok, ich sehe, ich brauche meinen 2 Cent zu setzen. Aus der Antwort des Autors ich denke, die „Priorität erhalten“ Technik ist genau das, was hier gebraucht wird. Es ist möglich, die Diskussion zu finden in „ Erlang: Priorität Frage hier auf SO erhalten“. Die Idee ist, Nachrichten mit hohen Priorität zuerst zu akzeptieren und andere Nachrichten nur in Abwesenheit von hohen Priorität diejenigen zu akzeptieren.
Als Scala Schauspieler sehr ähnlich sind Erlang, eine triviale Code dies implementieren würde wie folgt aussehen:
def act = loop {
reactWithin(0) {
case msg: HighPriorityMessage => // process msg
case TIMEOUT =>
react {
case msg: HighPriorityMessage => // process msg
case msg: LowPriorityMessage => // process msg
}
}
}
Das funktioniert folgendermaßen wie. Ein Akteur hat eine Mailbox (queue) mit Meldungen. Das receive
(oder receiveWithin
) Argument ist eine Teilfunktion und Schauspieler Bibliothek sucht nach einer Nachricht in einer Mailbox, die auf diese Teilfunktion angewandt werden können. In unserem Fall wäre es nur ein Ziel HighPriorityMessage
sein. Also, wenn Schauspieler Bibliothek eine solche Nachricht findet, gilt es unsere Teilfunktion und wir die Verarbeitung einer Nachricht von hoher Priorität. Andernfalls reactWithin
mit Timeout 0 ruft unsere Teilfunktion mit dem Argument TIMEOUT
und wir sofort versuchen, jede mögliche Nachricht aus der Warteschlange zu verarbeiten (wie es für eine Nachricht wartet, wir nicht eine Möglichkeit bekommen HighPriorityMessage
ausschließen kann).
Andere Tipps
Es klingt wie das Problem, das Sie beschreiben, nicht gut geeignet, um den Schauspieler Subsystems . Ein Actor
ist entworfen, um der Reihe nach seine Meldungswarteschlange zu verarbeiten:
- Was soll passieren, wenn der Schauspieler Durchführung der Hintergrund Arbeit und eine neue Aufgabe kommt?
Ein Schauspieler kann nur herausfinden, darüber ist er kontinuierlich seine mailbox
prüft, wie es die Aufgabe Hintergrund ausführt. Wie würden Sie diese (das heißt, wie Sie die Hintergrundaufgaben als Arbeitseinheit codieren würde, so dass der Schauspieler halten könnte zu unterbrechen und die Überprüfung der Mailbox) implementieren?
- Was soll passieren, wenn der Schauspieler viele Hintergrundaufgaben in seiner Mailbox vor der Hauptaufgabe hat?
Sie diese Hintergrundaufgaben weg bekommen geworfen oder an einem anderen Akteur gesendet? Wenn letzteres der Fall, wie können Sie die CPU-Zeit verhindern, dass der Schauspieler gegeben werden, um die Aufgaben zu erfüllen?
Alles in allem, es klingt viel wie Sie brauchen eine raster Stil Software zu erkunden, die im Hintergrund (wie Daten Synapse) laufen können!
Unmittelbar nach der diese Frage habe ich versucht, etwas ganz whacky Code aus und es scheint zu funktionieren. Ich bin nicht sicher, obwohl, wenn es eine Gotcha drin.
import scala.actors._
object Idling
object Processor extends Actor {
start
import Actor._
def act() = {
loop {
// here lie dragons >>>>>
if (mailboxSize == 0) this ! Idling
// <<<<<<
react {
case msg:NormalMsg => {
// do the normal work
reply(answer)
}
case Idling=> {
// do the idle work in chunks
}
case msg => println("Rcvd unknown message:" + msg)
}
}
}
}
Erklärung
Jeder Code in das Argument von loop
aber vor dem Aufruf von react
scheint genannt zu werden, wenn die Schauspieler über zu Warten auf eine Nachricht ist. Ich sende eine Nachricht an Idling
Selbst hier. Im Handler für diese Meldung stelle ich sicher, dass die Mailbox-Größe 0, bevor die Verarbeitung zu tun.