Actor - Actor API

顶级Actor

import akka.actor.{ActorSystem, DeadLetter}

object AkkaActor extends App {

import DemoActor._

println("Hello, world!")
val system = ActorSystem("mySystem")
val demoActor = system.actorOf(props(42), "demoActor")
system.eventStream.subscribe(demoActor, classOf[DeadLetter])
println(s"demoActor created !")
demoActor ! 88
println(s"ready to kill demoActor's child")
demoActor ! "kill"
}
  1. 创建顶级actordemoActor
  2. 订阅deadLetter
  3. 发送消息 88
  4. 停止 demoActor下的myActor

demoActor

import akka.actor.{Actor, ActorIdentity, ActorLogging, DeadLetter, Identify, Props, Terminated}
object DemoActor {
/**
* Create Props for an actor of this type.
*
* @param magicNumber The magic number to be passed to this actor’s constructor.
* @return a Props for creating this actor, which can then be further configured
* (e.g. calling `.withDispatcher()` on it)
*/
def props(magicNumber: Int): Props = Props(new DemoActor(magicNumber))
}

class DemoActor(magicNumber: Int) extends Actor with ActorLogging {

import MyActor._

println(s"magicNumber: $magicNumber")
val myActor = context.actorOf(MyActor.props, "myActor")
val identifyId = 1
println(s"create myActor: ${myActor.path}")
context.actorSelection("myActor") ! Identify(identifyId)

context.watch(myActor)
println("watching myActor")


def receive = {
case ActorIdentity(`identifyId`, Some(ref)) =>
println(s"get actorRef: $ref")
case ActorIdentity(`identifyId`, None) => println("not found the actorRef")
case x: Int =>
myActor ! Greeting(s"Vincent Guo with params $x")

case "kill" =>
context.stop(myActor);
println("stopping myActor")
myActor ! Greeting(s"after kill")
case DeadLetter(msg, from, to) =>
log.info("get DEAD LETTER")
self ! msg
case Terminated(`myActor`) => println(s"$myActor finished")
case m => println(m)
}

}
  1. 创建子Actor myActor
  2. 用actorSelection 以路径才获得actorRef
  3. watch 用来监听 myActor的 Terminated 事件
  4. context.stop(myActor) 停止子actor

myActor

class MyActor extends Actor {
val log = Logging(context.system, this)

import MyActor._

override def preStart(): Unit = {
println(s"${self} preStart")
}

override def postStop(): Unit = {
println(s"${self} postStop")
}

override def preRestart(reason: Throwable, message: Option[Any]): Unit = {
println(s"${self} preRestart")
context.children foreach { child ⇒
context.unwatch(child)
context.stop(child)
}
println("ready to invoke postStop")
postStop()
}

override def postRestart(reason: Throwable): Unit = {
println(s"${self} postRestart")
println(s"ready to preStart")
preStart()
}

def receive = {
case Greeting(greeter) =>
log.info(s"I was greeted by $greeter.")
case Goodbye => log.info("Someone said goodbye to me.")
}
}
  1. override actor生命周期
  2. 获取事件并打印

Output

Hello, world!
magicNumber: 42
demoActor created !
ready to kill demoActor's child
create myActor: akka://mySystem/user/demoActor/myActor
Actor[akka://mySystem/user/demoActor/myActor#1608259142] preStart
watching myActor
stopping myActor
get actorRef: Actor[akka://mySystem/user/demoActor/myActor#1608259142]
Actor[akka://mySystem/user/demoActor/myActor#1608259142] postStop
[INFO] [04/27/2017 22:21:22.664] [mySystem-akka.actor.default-dispatcher-4] [akka://mySystem/user/demoActor/myActor] I was greeted by Vincent Guo with params 88.
[INFO] [04/27/2017 22:21:22.670] [mySystem-akka.actor.default-dispatcher-3] [akka://mySystem/user/demoActor/myActor] Message [MyActor$Greeting] from Actor[akka://mySystem/user/demoActor#751608355] to Actor[akka://mySystem/user/demoActor/myActor#1608259142] was not delivered. [1] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
[INFO] [04/27/2017 22:21:22.670] [mySystem-akka.actor.default-dispatcher-3] [akka://mySystem/user/demoActor] get DEAD LETTER
Greeting(after kill)
Actor[akka://mySystem/user/demoActor/myActor#1608259142] finished
  1. 可以看到actor的启动和stop过程
  2. 用路径获取actorRef成功
  3. 死信消息拿到