将Scala演员转变为Akka演员:一个实例调用方法

时间:2012-02-16 13:04:52

标签: scala actor akka

最近我从scala actor转换为akka actor,但注意到akka actor使用ActorRef而不是实例对象:

val actorRef: ActorRef = Actor.actorOf(new MyActor)

所以我试过了:

val myActor = new MyActor
val actorRef: ActorRef = Actor.actorOf(x)

...同时拥有:1)ActorRef发送消息,2)MyActor来调用方法。
但我得到了:

akka.actor.ActorInitializationException: ActorRef for instance of actor [MyActor] is not in scope.

所以我的问题是:如何获得一个我可以调用ActorRef的实例(某种类型) - 就像!这样的方法以及来自MyActor实例的方法?

2 个答案:

答案 0 :(得分:14)

你正在做的是一个可怕的想法。所以现在就停下来,离开键盘,然后转到the Akka Documentation并阅读Actors。

考虑一下:

class YourActor extends Actor {
  var mutableStuff = ...
  def receive = {
    case _ =>
      // mess with mutableStuff
  }
  def publicMethod = // mess with mutableStuff
}

现在,设置系统并开始发送消息并从其他线程调用该方法。吊杆!

你正在做精确 Akka和Actor模型可以帮助你预防。你实际上是向后弯腰以打破他们已经修复过的东西:)他们不会让你这么做。

现在,您可以直接访问方法进行单元测试,但需要一个TestActorRef。在阅读文档时,请阅读有关测试的部分。

答案 1 :(得分:1)

我能做到的最好的是以下,非常脏:
还有更好的方法吗?

import akka.actor._

trait ActorCom {
  var actorRefForInitialization: ActorRef = _
  lazy val actorRef: ActorRef = actorRefForInitialization
  def ?(message: Any)(implicit channel: UntypedChannel = NullChannel, timeout: Actor.Timeout = Actor.defaultTimeout) = actorRef ? message
  def !(msg: Any)(implicit sender: UntypedChannel) = actorRef ! msg
  def start = actorRef.start
}

object AkkaActorFactory {
  def apply[A <: Actor](newInstance: => A with ActorCom): A with ActorCom = {
    var instance: Option[A with ActorCom] = None
    val actorRef = Actor.actorOf({
      instance = Some(newInstance)
      instance.get
    })
    instance.get.actorRefForInitialization = actorRef
    instance.get.actorRef // touch lazy val in ActorCom, to make it equal to actorRef and then its fixed (immutable)
    instance.get
  }
}

class MyActor extends Actor {
  def receive = {
    case "test1" => println("good")
    case "test2" => println("fine")
    case _       => println("bad")
  }
  def sendTestMsg2Myself = self ! "test2"
}

val myActor = AkkaActorFactory(newInstance = new MyActor with ActorCom)
myActor.start
myActor ! "test1"
myActor.sendTestMsg2Myself // example for calling methods on MyActor-instance
myActor ! PoisonPill