2017-07-14 4 views
0

ich diesen Code schriebWarum ist meine Schauspieler erstellt 2 mal

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) 
} 

Ich nenne es mit diesem Client-Code

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]) 
    } 
} 

ich die Ausgabe

going to start my test actor 
going to start my test actor 
Hello foo 
Hello foo 
came inside stop 
came inside stop 

Meine Frage sehen ist, dass Im Companion-Objekt hatte ich das Props-Objekt als val erstellt und daher gab es nur 1 val und das 1 val hatte 1 Instanz von new TestActor

Im Client verwendeten beide Klassen die gleiche Instanz des Aktorsystems. Daher hätte es nur 1 Akteur geben sollen und beide Nachrichten von Klasse A und Klasse B sollten zum selben Akteur gegangen sein.

Aber es scheint, dass beide Klassen ihre eigenen Actor-Instanzen haben.

+0

Was sollte 'Requisiten (neue TestActor)' tun? Ich habe Mühe zu verstehen, welchen Konstruktor Sie verwenden möchten. Jeder Aufruf von 'system.actorOf' erstellt außerdem eine neue Instanz dieses Akteurs. Wenn Sie Ihren Akteur nur einmal erstellen möchten, können Sie ihn auch einfach außerhalb von 'ClassB' und' ClassA' erstellen und an ihn übergeben, wie Sie es mit dem ActorSystem tun. – mfirry

Antwort

3

Meine Frage ist, dass in dem Begleitobjekt ich die Requisiten als val Objekt geschaffen hatte, und deshalb gibt es nur 1 val und 1 val hatte 1 Instanz von new TestActor

Nicht wirklich. Ja, Sie definieren eine val, aber diese val ist eine Props. Die Props Klasse ist im Wesentlichen ein Rezept zum Erstellen eines Schauspielers. Was Sie definieren, ist ein einziges unveränderliches Rezept zum Erstellen eines TestActor. Dieses Rezept kann mehrfach verwendet werden, wenn Sie zweimal ac.actorOf(TestActor.props) anrufen. Beide Aufrufe verwenden dasselbe Props Rezept, um ein neues TestActor zu erstellen; das heißt, Sie verwenden das gleiche Rezept, um zwei TestActor Instanzen zu erstellen.

Um einen einzelnen TestActor wiederzuverwenden, tun Sie was @mfirry vorgeschlagen und erstellen Sie diesen Akteur außerhalb von ClassA und ClassB. Hier ist eine Möglichkeit, das zu tun:

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

Dies wird verursacht durch actorOf erstellt einen neuen Akteur, so für zweimal actorOf wird es 2 TestActor erstellen. Sie können actorSelection verwenden, um die zweite Schöpfung zu vermeiden, wie:

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]) 
    } 
} 
Verwandte Themen