如何存储 scala actor 引用?

发布于 2024-10-16 16:08:09 字数 1350 浏览 1 评论 0原文

您好,我是 Scala 新手,我无法弄清楚如何在第二个参与者中存储参与者引用,以便稍后发送消息。在我的代码中,我尝试向一个演员发送一条测试消息。当它收到此消息时,它应该存储对第二个参与者的引用(OutputChannel),并且稍后应该能够向第二个参与者发送消息。我不想使用reply(),因为我需要仅在调用响应时发送消息。这是代码。感谢您的帮助!

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

Hello I am new to Scala and I have failed to figure out how one can store an actor reference within a second actor, for sending a message at a later time. In my code I try to send a test message to one actor. when it receives this message it should store the reference (OutputChannel) to the second actor and at a later time should be able to send a message to the second actor. I did not want to use the reply() as I need the message to be sent only when i invoke the respond. Here is the code. Thanks for any help!

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

來不及說愛妳 2024-10-23 16:08:09

1.您可以创建一个集中的参与者注册表。为了避免重新发明轮子,您可以使用一个好的现有实现 - Akka 的 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)
    }
  }

}

1. You can create a centralized actor registry. To avoid reinventing the wheel, you can use a good existing implementation - Akka's Actor Registry (or, at least, get inspired with it).

2 You can avoid using mutable list of actor references passing it through react loop:

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

}
童话里做英雄 2024-10-23 16:08:09

一种方法是创建一个 Actor Factory 来存储可以从任何地方获取的 Actor。

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 中供以后使用,就像在 main 中显式声明的 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 创建并存储 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

One way to do it is to create an Actor Factory that stores actors that you can grab from anywhere.

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

Messages can be either objects (with no "payload"), or can be classes that contain data

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

Here are a couple of actor types. The Actor2 instance is instantiated "on-the-fly", and stored in the ActorFactory for later use, as is the Actor1 instance that is explicitly declared in the main

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

The following ActorFactory creates and stores actors. Here, you can create multiple instances of a type of actor, and store by name.

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

    }

}

The output of this is

MessageType1 received
Hello from actor 2 instance
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文