Akka 的Actor
从第一篇Akka笔记的介绍中,我们是从很高的高度去观察Akka工具箱中的Actors。在这篇笔记的第二篇,我们会看一下Actors中的消息部分。而且延续上一次的例子,我们还会使用同样的学生与老师的例子。
在Actor消息的第一部分,我们会建立一个Teacher Actor,而且会使用一个叫StudentSimulatorApp的主程序。
回顾学生-老师模式的细节
现在考虑下StudentSimulatorApp单独发消息给TeacherActor。当我说到StudentSimulatorApp,就只是意思是一个常规的带main函数的主程序。
这张图传递的意思是:
(如果太复杂,别担心,我们会详细过一遍)
1.学生创建了一个叫ActorSystem的东西
2.它用ActorSystem来创建一个叫ActorRef的东西。QuoteRequest消息被发送到ActorRef(一个TeacherActor的代理)
3.Actor ref同样把消息发给Dispatcher
4.Dispatcher将消息放入到目标Actor的邮箱中(MailBox)
5.Dispatcher将Mail放到一个线程中(下节详细介绍)
6.MailBox取出一个消息并且最后将消息送给实际的Teacher Actor的接收方法。
就像我说的,别担心。下面我们看看每一步的细节。你可以在后面重新回来看下这五步。
STUDENTSIMULATORAPP程序
我们用StudentSimulatorApp启动JVM并且初始化ActorSystem。
就像图片上画的,这个StudentSimulatorApp
1.创建了一个ActorSystem
2.使用ActorSustem创建了一个Teacher Actor的代理(ActorRef)
3.给代理发送QuoteRequest(请求格言)消息。
让我们一起看下这三点。
1.创建 一个ActorSystem
ActorSystem是一个进入Actor世界的入口点。ActorSystem在创建和停止Actors的时候自始至终都存在着。并且在关掉整个Actor环境的时候也存在着。
在另一个方面,Actors是按层级划分的,ActorSystem可以类比为对于所有Actor的java.lang.Object基类对象或者scala.Any- 意思是它是所有Actors的根对象。当你用ActorSystem的actorof方法创建了一个Actor对象,你实际上创建了一个ActorSystem下一个一个子Actor。
初始化ActorSystem的代码类似于这个样子
val system=ActorSystem("UniversityMessageSystem")
这里的UniversityMessageSystem就是一个你给ActorSystem的昵称。
2.创建一个TeacherActor的代理?
让我们看下下面的片段:
'val teacherActorRef:ActorRef=actorSystem.actorOf(props[TeacherActor])'
actorOf是ActorSystem中的Actor的创建方法。但是,你可以看见这个方法并不返回一个TeacherActor。它返回一个类型是ActorRef的东西。
ActorRef是一个真实Actors的代理。客户端并不直接跟Actor对话。这这种Actor的模型是为了防止TeacherActor的自定义/私有方法或变量被直接访问。
你只会直接给ActorRef发送消息并且消息最终会到达实际的Actor。你永远不能直接跟Actor交互。要是你找到一些方式干这个,你会被大家诅咒。
3.给代理发送一个QuoteRequest
你只需要将QuoteRequest消息tell告诉ActorRef。这个告诉的方法在Actor里面是!叹号。(ActorRef也有一个tell方法,作用是委托回调给!)
'//send a message to the Teacher Actor'
'teacherActorRef!QuoteRequest'
这就没了!
如果你觉得我骗你,下面是StudentSimulatorApp的代码:
STUDENTSIMULATORAPP.SCALA
1 package me.rerun.akkanotes.messaging.actormsg1 2 3 import akka.actor.ActorSystem 4 import akka.actor.Props 5 import akka.actor.actorRef2Scala 6 import me.rerun.akkanotes.messaging.protocols.TeacherProtocol._ 7 8 9 object StudentSimulatorApp extends App{ 10 11 //Initialize the ActorSystem 12 val actorSystem=ActorSystem("UniversityMessageSystem") 13 14 //construct the Teacher Actor Ref 15 val teacherActorRef=actorSystem.actorOf(Props[TeacherActor]) 16 17 //send a message to the Teacher Actor 18 teacherActorRef!QuoteRequest 19 20 //Let's wait for a couple of seconds before we shut down the system 21 Thread.sleep (2000) 22 23 //Shut down the ActorSystem. 24 actorSystem.shutdown() 25 26 }
不过,我确实撒了一个小慌。你需要shutdown ActorSystem或者让JVM一直跑。我给这个main线程sleep一下只是为了给TeacherActor一点时间来完成它的任务。我知道这听起来有点傻。别担心这个。我们后面会写一些测试用例来避免这个。