我写了这段代码
class TestActor extends Actor {
override def preStart(): Unit = {
println("going to start my test actor")
}
override def postStop(): Unit = {
println("came inside stop")
}
def receive = {
case msg: TestMessage => sender ! s"Hello ${msg.name}"
}
}
object TestActor {
val props = Props(new TestActor)
case class TestMessage(name: String)
}
我使用此客户端代码调用它
object MyApp extends App {
val ac = ActorSystem("TestActorSystem")
val a = new ClassA(ac).sayHello()
val b = new ClassB(ac).sayHello()
for {
msg1 <- a
msg2 <- b
} {
println(msg1)
println(msg1)
}
Await.result(ac.terminate(), Duration.Inf)
}
class ClassA(ac: ActorSystem) {
def sayHello(): Future[String] = {
implicit val timeout = Timeout(5 seconds)
val actor = ac.actorOf(TestActor.props)
val msg = actor ? TestActor.TestMessage("foo")
msg.map(_.asInstanceOf[String])
}
}
class ClassB(ac: ActorSystem) {
def sayHello() : Future[String] = {
implicit val timeout = Timeout(5 seconds)
val actor = ac.actorOf(TestActor.props)
val msg = actor ? TestActor.TestMessage("bar")
msg.map(_.asInstanceOf[String])
}
}
我看到输出
going to start my test actor
going to start my test actor
Hello foo
Hello foo
came inside stop
came inside stop
我的问题是,在伴侣对象中我创建了props对象作为val,因此只有1个val,而1个val有1个new TestActor
实例
在客户端中,两个类都使用了相同的actor系统实例。因此,应该只有1个actor,来自classA和ClassB的两个消息都应该转到同一个actor。
但似乎两个类都有自己的Actor实例。
答案 0 :(得分:3)
我的问题是,在伴侣对象中我创建了props对象作为val,因此只有1个val,而1个val有1个
new TestActor
实例
不是真的。是的,您定义了一个val
,但val
是Props
。 Props
类本质上是创建actor的秘诀。您定义的是用于创建TestActor
的单个不可变配方。此配方可以多次使用,这是您在拨打ac.actorOf(TestActor.props)
两次时所做的事情。这两个调用都使用相同的Props
配方来创建新的TestActor
;也就是说,您使用相同的配方来创建两个TestActor
实例。
要重复使用单个TestActor
,请执行@mfirry建议并在ClassA
和ClassB
之外创建此角色。这是一种方法:
object MyApp extends App {
val ac = ActorSystem("TestActorSystem")
val testActor = ac.actorOf(TestActor.props)
val a = new ClassA(ac).sayHello(testActor)
val b = new ClassB(ac).sayHello(testActor)
for {
msg1 <- a
msg2 <- b
} {
println(msg1)
println(msg1)
}
Await.result(ac.terminate(), Duration.Inf)
}
class ClassA(ac: ActorSystem) {
def sayHello(actor: ActorRef): Future[String] = {
implicit val timeout = Timeout(5 seconds)
val msg = actor ? TestActor.TestMessage("foo")
msg.map(_.asInstanceOf[String])
}
}
class ClassB(ac: ActorSystem) {
def sayHello(actor: ActorRef): Future[String] = {
implicit val timeout = Timeout(5 seconds)
val msg = actor ? TestActor.TestMessage("bar")
msg.map(_.asInstanceOf[String])
}
}
答案 1 :(得分:1)
这是由actorOf
创建一个新演员引起的,所以两次actorOf
它会创建2 TestActor
。您可以使用actorSelection
来避免第二次创建,例如:
class ClassA(ac: ActorSystem) {
def sayHello(): Future[String] = {
implicit val timeout = Timeout(5 seconds)
val actor = ac.actorOf(Props[TestActor], "test")
println(actor.path)
val msg = actor ? TestMessage("foo")
msg.map(_.asInstanceOf[String])
}
}
class ClassB(ac: ActorSystem) {
def sayHello() : Future[String] = {
implicit val timeout = Timeout(5 seconds)
val actor = ac.actorSelection("akka://TestActorSystem/user/test")
val msg = actor ? TestMessage("bar")
msg.map(_.asInstanceOf[String])
}
}