2011-02-10 18 views
6

Hola, soy nuevo en Scala y no he podido averiguar cómo se puede almacenar una referencia de actor en un segundo actor, para enviar un mensaje en otro momento. En mi código intento enviar un mensaje de prueba a un actor. cuando recibe este mensaje, debe almacenar la referencia (OutputChannel) al segundo actor y en un momento posterior debe poder enviar un mensaje al segundo actor. No quería usar la respuesta() ya que necesito que el mensaje se envíe solo cuando invoco la respuesta. Aquí está el código. ¡Gracias por cualquier ayuda!¿cómo puedo almacenar una referencia de scala actor?

import scala.actors.Actor 
import scala.actors.Actor._ 
import scala.collection.mutable.ArrayBuffer 
import scala.actors.OutputChannel 

object testactors { 

    case object TestMessage 
    case object Respond 

    class TestActor(name: String) extends Actor { 
     private var source : ArrayBuffer[OutputChannel[Any]] = new ArrayBuffer 

     def act() { 
      loop { 
       react{ 
        case TestMessage => 
         println("i received a TestMessage " + name) 
         source += sender 
        case Respond => 
         println("i received a ResponseMessage " + name) 
       } 
      } 
     } 

     def sendMessage(dest: Actor) = dest ! TestMessage 

     def respond = { 
      println("responding... " + name) 
      source(0) ! Respond 
     } 
    } 


    def main(args: Array[String]) { 
     val actor1 = new TestActor("one") 
     actor1.start 

     val actor2 = new TestActor("two") 
     actor2.start 

     actor1.sendMessage(actor2) 

     Thread.sleep(5000) 

     actor2.respond 
    } 
} 

Respuesta

4

1. Usted puede crear un registro centralizado el actor. Para evitar reinventar la rueda, puede usar una buena implementación existente: Akka's Actor Registry (o, al menos, inspírese con ella).

Puede evitar el uso de la lista de referencias mutables actores pasándolo a través reaccionan bucle:

case class AddActor(actor: Actor) 
case object NotifyAll 

class StatefulActor extends Actor { 

    override def act = loop(Nil) 

    def loop(actors: List[Actor]):Unit = { 
    react { 
     case AddActor(actor) => println("Added new actor") 
     loop(actor :: actors) 
     case NotifyAll => println("Notifying actors: " + actors) 
     actors.foreach(_ ! "Hi!") 
     loop(actors) 
     case unknown => println("Unknown message: " + unknown)  
     loop(actors) 
    } 
    } 

} 
+0

esto encaja perfectamente con el problema que tuve. muchas gracias Vasil! – spydadome

+0

@spydadome, eres bienvenido :) –

1

Una forma de hacerlo es crear una Actor Factory que almacene actores que pueda obtener desde cualquier lugar.

import scala.actors.Actor 
import scala.actors.Actor._ 
import scala.collection.mutable._ 

Los mensajes pueden ser tanto objetos (sin "carga útil"), o pueden ser clases que contienen datos

abstract class Message 
case object MessageType1 extends Message 
case class MessageType2(str:String) extends Message 

Aquí hay un par de tipos de actores. La instancia Actor2 se crea una instancia "en la marcha", y se almacena en el ActorFactory para su uso posterior, como es el caso Actor1 que se declara explícitamente en el principal

class MyActor1 extends Actor { 
    def act() { 
     loop { 
      react { 
       case MessageType1 => 
        println("MessageType1 received") 
        ActorFactory.getActor2("B") ! MessageType2("Hello") 
       case _ => 
      } 
     } 
    } 
} 

class MyActor2 extends Actor { 
    def act() { 
     loop { 
      react { 
       case MessageType2(theString) => 
        println(theString+" from actor 2 instance") 
       case _ => 
      } 
     } 
    } 
} 

La siguiente ActorFactory crea y almacena los actores. Aquí puede crear múltiples instancias de un tipo de actor y almacenar por nombre.

object ActorFactory { 
    val actorMap = new HashMap[String,Actor] with SynchronizedMap[String,Actor] 

    def getActor1(symbol:String): Actor = { 
     val actor = actorMap.getOrElseUpdate(symbol,new MyActor1().start) 
     actor 
    } 

    def getActor2(symbol:String): Actor = { 
     val actor = actorMap.getOrElseUpdate(symbol,new MyActor2().start) 
     actor 
    } 
} 

object Test { 

    def main(args : Array[String]) {      

     val actor1 = ActorFactory.getActor1("A") 
     actor1 ! MessageType1 

    } 

} 

La salida de este es

MessageType1 received 
Hello from actor 2 instance 
+0

muchas gracias Bruce! ¡Funciona para mi ahora! – spydadome

Cuestiones relacionadas