從第一篇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一點時間來完成它的任務。我知道這聽起來有點傻。別擔心這個。我們后面會寫一些測試用例來避免這個。