[关闭]
@xtccc 2016-03-09T02:34:07.000000Z 字数 2262 阅读 2567

Actor 生命周期

给我写信
GitHub

此处输入图片的描述

Akka


1. Actor生命周期


QQ20160306-0@2x.png-341.8kB

参考 Actor Lifecycle




2. 终止Actor


终止Actor有两种方式:

  1. 对于top-level actor: ActorSystem#stop
  2. 对于普通的actor及其child actors: ActorContext#stop

终止Actor的过程是异步的,即stop的可能在actor真正终止前就返回了。异步终止的特性会导致: Since stopping an actor is asynchronous, you cannot immediately reuse the name of the child you just stopped; this will result in an InvalidActorNameException. Instead, watch the terminating actor and create its replacement in response to the Terminated message which will eventually arrive.



内部的实现流程:

Termination of an actor proceeds in two steps: first the actor suspends its mailbox processing and sends a stop command to all its children, then it keeps processing the internal termination notifications from its children until the last one is gone, finally terminating itself (invoking postStop, dumping mailbox, publishing Terminated on the DeathWatch, telling its supervisor). If one of the actors does not respond (i.e. processing a message for extended periods of time and therefore not receiving the stop command), this whole process will be stuck.



  1. package cn.gridx.scala.akka.tutorial.lifecycle
  2. import akka.actor.{Props, ActorRef, ActorSystem, Actor}
  3. object StopActors {
  4. def main(args: Array[String]): Unit = {
  5. val system = ActorSystem("Stop-Actors-Example")
  6. val actorA = system.actorOf(Props(classOf[ActorA], 5))
  7. Thread.sleep(1000)
  8. actorA ! "Spawn"
  9. Thread.sleep(2000)
  10. actorA ! "Halt"
  11. Thread.sleep(10000)
  12. system.shutdown
  13. }
  14. trait Msg
  15. case class RequestMsg() extends Msg
  16. class ActorA(childrenNum: Int) extends Actor {
  17. val children: Array[ActorRef] = new Array[ActorRef](childrenNum)
  18. def receive = {
  19. case "Spawn" =>
  20. println("[Actor A] 即将创建children actors")
  21. for (i <- 0 until children.size) // 为自己创建若干个child actors
  22. children(i) = context.actorOf(Props(classOf[ActorB], i))
  23. println(s"[Actor A] ${childrenNum}个children actors创建完毕")
  24. case "Halt" =>
  25. children.map(context.stop) // 先把children都终止(这一步实际上是不需要的)
  26. context stop self // 再终止自身
  27. }
  28. override def preStart = {
  29. println("I'm ActorA, I will be started !")
  30. }
  31. override def postStop = {
  32. println("I'm ActorA, I am stopped !")
  33. }
  34. }
  35. class ActorB(n: Int) extends Actor {
  36. def receive = {
  37. case _ => println("[Actor B] 这是啥消息,我也不知道")
  38. }
  39. override def preStart = {
  40. println(s"I'm ActorB-#$n, I will be started !")
  41. }
  42. override def postStop = {
  43. println(s"I'm ActorB-#$n, I am stopped !")
  44. }
  45. }
  46. }

运行输出为:
QQ20160307-0@2x.png-114.8kB

实际上,如果actorA有若干个children,那么当我们针对actorA调用stop时,它的child actors会自动地先被终止,因此并不需要对child actors逐个调用stop。



如果要求终止某个actor时,它正在处理消息,怎么办?

该Actor对当前正在处理的消息会继续处理,但是不会处理mailbox中剩下的其他消息。在默认情况下,mailbox中剩余的消息会被发送到ActorSystem的deadLetters(这取决于mailbox的实现)。




添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注