我的应用程序中有一个单例参与者系统,除了在同一个 JVM 中加载和卸载同一个应用程序进行测试时,我有一个错误,因为我在启动过程中尝试重新创建一个参与者已经存在。
结果,我得到了一个,akka.actor.InvalidActorNameException
因为 Actor 名称不是唯一的。
我正在寻找一种方法来根据演员系统顺利关闭演员,而无需关闭演员系统本身。哪个是合理的策略?
这并不完全回答您的问题 - “ ......一种平滑关闭演员的方法...... ”,但您提到您能够在同一个 JVM 中启动两个应用程序。
你能让你的actor系统在应用程序实例中成为单例而不是整个JVM中的单例吗?
您将拥有两个独立的演员系统,不会有名称冲突,也不必启动/停止特定的演员。
我想问题可能是如果某些参与者正在与外部世界交互,例如从 JMS 消费一些消息等。那么哪个参与者系统正在处理它们就不是很明显了。
你想要这样的东西吗?
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 和消息是异步的。如果您在杀死他之后尝试创建一个演员,则该名称不可用。在创建新演员之前尝试一个 Thread.sleep ,它将起作用.. :)