2009-06-17 9 views
2

Ich möchte Schauspieler in einem Programm verwenden, in dem ich einige Einschränkungen bezüglich der Behandlung einiger Schauspieler habe, als wären sie Warteschlangen. Angenommen, ich habe ein externes System, auf das Änderungsereignisse angewendet werden, und auch einen Cache für die Daten des externen Systems. So habe ich 2 Schauspieler:Scala-Schauspieler als single-threaded-Warteschlangen

  1. ChangeApplicationActor
  2. CacheActor

Im Rahmen der ChangeApplicationActor, wenn ich eine Änderung zu einem gewissen Einheit X im externen System anwenden, mag ich ein Ereignis schicken sagen die CacheActor zu synchronisieren:

val changeApplicationActor = actor { 
    loop { 
    react { 
     case ChangeInstruction(x) => 
     externalSystem.applyChange(x) 
     cacheActor ! Sync(x) 
    } 
    } 
} 

Aber ich habe jetzt zwei Anforderungen:

  1. Die CacheActor verfügt über einen internen Zustand und im Idealfall würde Ich mag es seine Sync Befehle sequentiell
  2. Wenn ich mit der CacheActor ‚s Posteingang ich am Ende zu verarbeiten für den gleichen Wert von x, dann mit zwei Sync(x) Anweisungen würde gerne den zweiten ignorieren (d. h Ich sollte nur eine anhängige Sync Anweisung für einen bestimmten Wert von x) haben

Gibt es eine Möglichkeit, einen Schauspieler zu zwingen, single-threaded zu sein? Gibt es eine Möglichkeit, auf das Postfach des Akteurs zuzugreifen und doppelte Ereignisse zu entfernen? Kann ich nicht vermeiden, die CacheActor als, um, kein Schauspieler zu implementieren?

+0

Natürlich könnte mein CacheActor nur ein dünner Wrapper um einen internen Thread plus Nachrichtenwarteschlange sein. Ich habe mich gefragt, ob es eine "elegantere" Lösung gibt. –

Antwort

5

Ein Aktor wird garantiert immer nur auf einem Thread ausgeführt, und die Nachrichten im Postfach des Aktors sind in FIFO-Reihenfolge, also ist # 1 da.

2 ist schwieriger, da es keine integrierte Unterstützung dafür gibt. Es gibt ein Attribut für den Akteur namens "Postfach". Sie können direkt auf das Postfach zugreifen, anstatt über Empfangen oder Reagieren. Sie müssen lediglich die entsprechenden Synchronisierungsnachrichten aus dem Postfach abrufen, bevor Sie mit der Verarbeitung der Nachricht fertig sind. Wenn Sie dies tun, müssen Sie auf dem Akteur synchronisieren, um zu verhindern, dass ein anderer Thread während eines Nachrichtenversands das Hinzufügen von Daten zum Postfach versucht.

Es sollte beachtet werden, dass die Synchronisierung auf dem Aktor die von der Bibliothek gemachten Deadlock-Freiheitsgarantien beseitigt und die Skalierbarkeit verringert. Aber von einem praktischen Standpunkt aus werden Sie wahrscheinlich in Ordnung sein.

+0

Ist das wirklich wahr, wenn man nur eine Nachricht gleichzeitig verarbeitet? Ich sehe es nicht einmal in Programmierung in Scala erwähnen? Ich bin mir ziemlich sicher, dass du falsch liegst. Auf Seite 593 heißt es: "Wenn [die reactive-Methode] eine Nachricht findet, die bearbeitet werden kann, plant [it] die Behandlung dieser Nachricht für die spätere Ausführung und löst eine Ausnahme aus". Das wichtige Stück ist "für die spätere Ausführung" –

+0

OK - scheint, als ob Sie richtig sind, tut mir leid. Ich stellte eine andere Frage: http://stackoverflow.com/questions/1007010/can-scala-actors-process-multiple-messages- simultan –

+0

Auch die MessageQueue-Dokumentation gibt ausdrücklich an, dass ich es von außerhalb des Pakets –