Saubere Actor Programmierung
... [ Seminar Programmiersprachen und -Systeme ] ... [ Inhaltsverzeichnis ] ... [ Abschluss ] ...
Übersicht: Saubere Actor Programmierung
Hilfsactor zum Blocken nutzen
Das Blockieren von Actors während der Verarbeitung von Nachrichten kann dazu führen, dass auch weitere Actors blockiert werden, die auf eine Antwort warten. Um dies zu verhindern, bietet es sich an, nicht den Actor selber zu blockieren, sondern einen Hilfsactor zu nutzen. Dann ist der eigentliche Actor weiterhin in der Lage Nachrichten zu verarbeiten.
Zu beachten ist, dass der Hilfsactor niemals Nachrichten empfangen darf, denn sonst könnte er wiederum andere Actors blockieren. So kann es niemals zu einem deadlock kommen. Im folgenden Beispiel wird eine blocken Funktion implementiert, die einen Hilfsactor für eine bestimmte Zeit blockt und danach dem Hauptactor eine Nachricht schickt, dass er weiter arbeiten kann. Dazu sollte die Referenz des Hauptactors gesichert werden. Während der Hilfsactor nun also blockiert, kann der Hauptactor ohne Probleme die zwischendurch ankommende Nachricht verarbeiten.
Beispiel für einen Hilfsactor zum Blocken:
val blockBspAct = actor {
def blocken(msec : Int) {
val ref = self
actor {
Thread.sleep(msec)
ref ! wachAuf()
}
}
var cnt = 0
loop {
react {
case msg : wachAuf =>
println(cnt + " Sekunden sind vergangen")
cnt += 1
if (cnt < 5)
blocken(1000)
else exit()
case msg =>
println("Zwischenmeldung: "+ msg)
}
}
}
//Input:
blockBspAct ! wachAuf()
actor {
Thread.sleep(2500)
blockBspAct ! "Nachricht von Hilfsactor nach 2,5 Sekunden"
}
0 Sekunden sind vergangen
1 Sekunden sind vergangen
2 Sekunden sind vergangen
Zwischenmeldung: Nachricht von Hilfsactor nach 2,5 Sekunden
3 Sekunden sind vergangen
4 Sekunden sind vergangen
Das Beispielprogramm
Hier ist also gut zu erkennen, dass der Actor in der Lage ist eine Zwischennachricht zu verarbeiten, obwohl er eigentlich gerade wartet.
Nur unveränderliche Nachrichten nutzen
Grundsätzlich ist es möglich alle Daten als Nachrichten zu verschicken, auch veränderliche. Allerdings sei es an dieser Stelle dringend angeraten nur unveränderliche Nachrichten zur Kommunikation zwischen Actors zu verwenden. Daher bieten sich die bisher vorgestellten case classes optimal an, da sie prinzipiell unveränderlich sind, wenn man es nicht explizit anders definiert. Außerdem sind in der Scala API noch viele weitere unveränderliche Datentypen vorgegeben, die bedenkenlos genutzt werden können.
Veränderliche Daten sollten immer nur von einem einzigen Actor genutzt werden. Dieser kann dann über das Nachrichtensystem Änderungen kontrolliert vornehmen, ohne das eine explizite Synchronisation nötig wäre.
Sofern es trotzdem nötig ist die veränderlichen Daten zu verschicken, sollte immer nur eine Kopie versendet werden. Dann kann die Anwendung weiterhin "thread-safe" arbeiten.
... [ Seminar Programmiersprachen und -Systeme ] ... [ Inhaltsverzeichnis ] ... [ Abschluss ] ...