как я могу сохранить ссылку на актера scala?

Здравствуйте, я новичок в Scala, и мне не удалось понять, как можно сохранить ссылку на актера во втором актере для отправки сообщения в более позднее время. В своем коде я пытаюсь отправить тестовое сообщение одному актеру. когда он получает это сообщение, он должен сохранить ссылку (OutputChannel) на второго актора, а позже должен иметь возможность отправить сообщение второму актору. Я не хотел использовать ответ(), так как мне нужно, чтобы сообщение было отправлено только тогда, когда я вызываю ответ. Вот код. Спасибо за любую помощь!

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

person spydadome    schedule 10.02.2011    source источник


Ответы (2)


1. Вы можете создать централизованный реестр субъектов. Чтобы не изобретать велосипед, вы можете использовать хорошую существующую реализацию — Akka's Actor Registry (или, по крайней мере, вдохновиться этим).

2 Вы можете избежать использования изменяемого списка ссылок на акторов, передавая его через цикл реагирования:

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)
    }
  }

}
person Vasil Remeniuk    schedule 10.02.2011
comment
это полностью соответствует моей проблеме. спасибо большое Василь! - person spydadome; 11.02.2011

Один из способов сделать это — создать фабрику актеров, в которой хранятся актеры, которых вы можете взять откуда угодно.

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 для последующего использования, как и экземпляр Actor1, явно объявленный в основном

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 создает и сохраняет актеров. Здесь вы можете создать несколько экземпляров типа актера и сохранить их по имени.

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
person Bruce Ferguson    schedule 10.02.2011