2011-02-10 44 views
6

你好,我是斯卡拉新手,我无法弄清楚如何在第二个演员中存储演员参考,以便稍后发送消息。在我的代码中,我尝试向一个演员发送测试消息。当它收到这条消息时,它应该将引用(OutputChannel)存储到第二个参与者,并在稍后时间能够向第二个参与者发送消息。我不想使用reply(),因为只有当我调用响应时才需要发送消息。这是代码。谢谢你的帮助!我该如何存储一个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 
    } 
} 

回答

4

您可以创建一个集中的演员注册表。为了避免重新发明轮子,你可以使用一个很好的现有实现 - 或者至少从中获得灵感。

你能避免使用演员引用的可变列表使其穿过反应循环:

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

这完全符合我所遇到的问题。非常感谢Vasil! – spydadome 2011-02-10 23:06:14

1

一种方法是创建一个Actor Factory,该Actor Factory存储您可以从任何地方抓取的演员。

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

消息可以是对象(没有“有效载荷”),或者可以是包含数据

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

类这里有几个演员类型。该Actor2实例的实例“上即时”,并存储在ActorFactory以备后用,因为是在主

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 _ => 
      } 
     } 
    } 
} 

以下ActorFactory创建和存储者明确宣布Actor1实例。在这里,您可以创建一个类型actor的多个实例,并按名称存储。

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 

    } 

} 

的这个输出是

MessageType1 received 
Hello from actor 2 instance 
+0

非常感谢布鲁斯!它现在适合我! – spydadome 2011-02-10 14:44:49