在使用Java進行併發編程時須要特別的關注鎖和內存原子性等一系列線程問題,而Actor模型內部的狀態由它本身維護即它內部數據只能由它本身修改(經過消息傳遞來進行狀態修改),因此使用Actors模型進行併發編程能夠很好地避免這些問題,Actor由狀態(state)、行爲(Behavior)和郵箱(mailBox)三部分組成html
如下經過學生與教師之間的郵件通訊來理解akka中的Actor模型編程
首先先只考慮學生單向發送消息給教師(學生--->教師),以下圖:
併發
圖解:app
下面再詳細的解釋每一步驟框架
首先StudentSimulatorApp會先啓動JVM並初始化ActorSystem
dom
如上圖所示,StudentSimulatorApp的主要工做爲:異步
ActorSystem做爲頂級Actor,能夠建立和中止Actors,甚至可關閉整個Actor環境,
此外Actors是按層次劃分的,ActorSystem就比如Java中的Object對象,Scala中的Any,
是全部Actors的根,當你經過ActorSystem的actof方法建立Actor時,實際就是在ActorSystem
下建立了一個子Actor。
可經過如下代碼來初始化ActorSystemide
val system = ActorSystem("UniversityMessageSystem")高併發
看看TeacherActor的代理的建立代碼ui
val teacherActorRef:ActorRef = system.actorOf(Props[TeacherActor])
你只需經過!方法將QuoteReques消息發送給ActorRef(注意:ActorRef也有個tell方法,其做用就委託回調給!)
techerActorRef!QuoteRequest
等價於teacherActorRef.tell(QuoteRequest, teacherActorRef)
完整StudentSimulatorApp代碼
object StudentSimulatorApp extends App{
//初始化ActorSystem
val actorSystem=ActorSystem("UniversityMessageSystem")
//構建teacherActorRef
val teacherActorRef=actorSystem.actorOf(Props[TeacherActor])
//發送消息給TeacherActor
teacherActorRef! QuoteRequest
Thread.sleep (2000)
//關閉 ActorSystem,若是不關閉JVM將不會退出
actorSystem.shutdown()
}
object TeacherProtocol{
case class QuoteRequest() //請求
case class QuoteResponse(quoteString:String) //響應
}
ActorRef將消息處理能力委派給Dispatcher,實際上,當咱們建立ActorSystem和ActorRef時,
Dispatcher和MailBox就已經被建立了
Dispatcher從ActorRef中獲取消息並傳遞給MailBox,Dispatcher封裝了一個線程池,以後在
線程池中執行MailBox。
protected[akka] override def registerForExecution(mbox: Mailbox, ...): Boolean = {
...
try {
executorService execute mbox
...
}
看看MailBox的實現,沒錯,其實現了Runnable接口
private[akka] abstract class Mailbox(val messageQueue: MessageQueue) extends SystemMessageQueue with Runnable
當ActorRef發送消息調用目標Actor的reveive方法時,MailBox中的run方法被執行,接着從消息隊列中取出一條消息並傳遞給Actor處理
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
//從list中隨機選出一條消息做爲迴應(這裏只print並沒迴應學生的請求)
val quoteResponse=QuoteResponse(quotes(Random.nextInt(quotes.size)))
println (quoteResponse)
}
}
}
TeacherActor的receive方法將匹配QuoteRequest消息
AKKA NOTES - ACTOR MESSAGING - 1
Akka框架——第一節:併發編程簡介
Akka Quickstart with Scala