如何在单例ActorSystem中管理actor关闭

时间:2013-02-11 08:57:39

标签: scala akka actor

我的应用程序中有一个单独的actor系统,这完全正常,除了在同一个JVM中加载和卸载相同的应用程序进行测试时,我有一个错误,因为我尝试在我的启动过程中重新创建已经存在的演员。

因此,我得到akka.actor.InvalidActorNameException,因为Actor名称不是唯一的。

我正在寻找一种方法来根据actor系统顺利关闭actor,而无需关闭actor系统本身。这是一个合理的策略吗?

2 个答案:

答案 0 :(得分:1)

这不完全是你问题的答案 - “ ......一种顺畅关闭演员的方法...... ”,但是你提到你能够在同一个节目中启动两个应用程序JVM。

你能否让你的actor系统在应用程序实例中成为 singleton而不是整个JVM中的singleton?

您将拥有两个独立的actor系统,您不会有名称冲突,也不必启动/停止特定的actor。

我想问题可能是一些演员正在与外界互动,例如从JMS等消费一些消息。那么哪个演员系统正在处理它们就不明显了。

答案 1 :(得分:0)

你想要这样的事吗?

object AkkaTest extends App {
  import akka.actor._
  import akka.pattern.ask
  import akka.util.Timeout
  import scala.concurrent.duration._

  val system = ActorSystem.create

  val supervisor = system.actorOf(Props[MasterOfPuppets], name = "masterOfPuppets")

  private object AllTerminated

  private class MasterOfPuppets extends Actor {

    var supervised = 0

    var waiterForTerminated: Option[ActorRef] = None

    def receive = {
      case actor: ActorRef =>
        context.watch(actor)
        supervised += 1
      case Terminated(dead) =>
        supervised -= 1
        if (supervised == 0) {
          waiterForTerminated.map(_ ! AllTerminated)
          waiterForTerminated = None
        }
      case AllTerminated =>
        if (supervised == 0) {
          sender ! AllTerminated
        } else {
          waiterForTerminated = Some(sender)
        }
    }
  }

  private class TestedActor extends Actor {
    def receive = {
      case a: Any => sender ! a
    }
  }

  implicit val timeout = Timeout(5.seconds) // needed for `?` below

  // Create first actor
  val actor1 = system.actorOf(Props[TestedActor], name = "name1")
  supervisor ! actor1
  actor1 ! PoisonPill

  val waitForIt = supervisor ? AllTerminated
  Await.result(waitForIt, 5.seconds)
  // Same name
  val actor2 = system.actorOf(Props[TestedActor], name = "name1")
  supervisor ! actor2

  println("ok then")
}

你的问题非常简单:Akka和消息是异步的。如果您在杀死他之后尝试创建一个演员,则该名称不可用。 在创建新actor之前尝试一下Thread.sleep,它将起作用.. :))