消息
我們只是讓QuoteRequest到ActorRef去但是我們根本沒見過消息類!
它是這樣的:
(一個最佳實踐是把你的消息類包裝在一個完整的對象里以利于更好的組織)
TeacherProtocol
package me.rerun.akkanotes.messaging.protocols
object TeacherProtocol{
case class QuoteRequest()
case class QuoteResponse(quoteString:String)
}
就像你知道的,QuoteRequest是用來發給TeacherActor的。Actor應該響應一個QuoteResponse回來。
分發者DISPATCHER和郵箱MAILBOX
ActorRef將消息處理功能委托給Dispatcher。在底層實現中,當我們創建一個ActorSystem和ActorRef的時候,一個Dispatcher和一個MailBox也被創建出來了。讓我們看下他們。
郵箱MailBox
Actor有一個MailBox(稍后我們會看到一個特例)。在我們的例子里,每個老師都有一個郵箱(mailbox)。老師需要檢查郵箱(mailbox)并且處理消息。在Actor的世界里,是另一種樣子-郵箱(mailbox),當它有機會它會使用Actor來完成它的工作。
郵箱維護一個先入先出的隊列來保存和處理消息- 跟我們常規的收件箱有點不一樣,常規的收件箱總是最新的郵件在最上面。
現在,分發者 dispatcher
分發者做的事很有趣。表面上看,分發者只是從ActorRef拿到消息然后將消息發給MailBox。但是在這個場景里有個很神奇的事情:
分發者包裝了ExecutorService(ForkJoinPool或者ThreadPoolExecutor)。 它用這個ExecutorService來執行MailBox。
看一下這個Dispathcer里的片斷:
protected[akka] override def registerForExecution(mbox: Mailbox, ...): Boolean = {
...
try {
executorService execute mbox
...
}
什么?你說你執行MailBox?
是的。我們已經看到了MailBox將所有消息維護在一個隊列里。當Executor運行MailBox時,MailBox必須是一個線程(Thread)。就是這樣,這就是MailBox的聲明和構造函數。
這里是Mailbox的簽名
private[akka] abstract class Mailbox(val messageQueue: MessageQueue) extends SystemMessageQueue with Runnable
TEACHER ACTOR
MailBox,當它的run方法被調用時,從隊列里獲取一條消息并把它發給Actor來處理。
在你將消息告知(tell)ActorRef的時候一定會調用到目標Actor的receive方法。
這里的TeacherActor是個基本類,維護一個格言列表(List)并自帶能處理消息的方法receive。
看下這里:
TeacherActor.scala
package me.rerun.akkanotes.messaging.actormsg1
import scala.util.Random
import akka.actor.Actor
import me.rerun.akkanotes.messaging.protocols.TeacherProtocol._
/*
* Your Teacher Actor class.
*
* The class could use refinement by way of
* using ActorLogging which uses the EventBus of the Actor framework
* instead of the plain old System out
*
*/
class TeacherActor extends Actor {
val quotes = List(
"Moderation is for cowards",
"Anything worth doing is worth overdoing",
"The trouble is you think you have time",
"You never gonna know if you never even try")
def receive = {
case QuoteRequest => {
import util.Random
//Get a random Quote from the list and construct a response
val quoteResponse=QuoteResponse(quotes(Random.nextInt(quotes.size)))
println (quoteResponse)
}
}
}
TeacherActor只接受一種消息格式-QuoteRequest(實際上,這個讓模式匹配默認case的方式是個好實踐,但這兒還是有個有趣的故事)
receive方法做的所有事是
- 根據模式匹配QuoteRequest
- 從格言的靜態列表(list)中隨機選取一個格言
- 構造一個QuoteResponse
- 將QuoteResponse打印到控制臺
代碼
完整項目可以在github下載。
文章來自微信平臺「麥芽面包」,微信號「darkjune_think」。轉載請注明。
文章列表