2017-07-14 73 views
0

我寫了這個代碼爲什麼我的演員創造了2次

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 

我的問題是,在同伴對象中,我創建了prop對象作爲val,因此只有1個val,而1 val有1個實例0

在客戶端中,兩個類都使用了actor系統的相同實例。因此應該只有一個演員,並且來自classA和ClassB的兩條消息應該已經到了同一個演員。

但似乎這兩個類都有自己的Actor實例。

+0

'Props(new TestActor)'應該做什麼?我很難理解你想要使用哪個'Props'構造函數。另外,每次調用'system.actorOf'都會創建該actor的新實例。如果你只想創建一次你的actor,那麼你可以在'ClassB'和'ClassA'之外創建它,並將它傳遞給它們,就像你使用ActorSystem一樣。 – mfirry

回答

3

我的問題是,在同伴的對象我創造了道具對象作爲VAL,因此,只有1個VAL和1個VAL了new TestActor

不是真的。是的,您定義了一個val,但valProps。類實際上是創建演員的配方。你所定義的是一個創建TestActor的單一的不可改變的配方。此配方可以多次使用,這是您在撥打ac.actorOf(TestActor.props)兩次時所要做的。這兩個調用都使用相同的Props配方創建新的TestActor;也就是說,您使用相同的配方來創建兩個TestActor實例。

要重新使用單個TestActor,請執行@mfirry建議的操作,並在ClassAClassB之外創建此演員。這裏有一種方法可以做到這一點:

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

這是由於actorOf會創建一個新的actor,所以對於兩次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]) 
    } 
}