17_Scala_Akka_Actor上
Akka 中Actor 模型是一種處理并發問題的解決方案

Actor模型工作機制說明
1 處理并發問題關鍵是要保證共享數據的一致性和正確性,因為程序是多線程時,多個線程對同一個數據進行修改,若不加同步條件,勢必會造成數據污染 但是當對關鍵代碼加入同步條件synchronized 后,實際上大并發就會阻塞在這段代碼,對程序效率有影響 2 若是用單線程處理,不會有數據一致性的問題,但是系統的性能又不能保證。 3 Actor 模型是一種處理并發問題的解決方案 4 Actor 之間只能用消息進行通信,給 Actor發消息,消息是有順序的(消息隊列),只需要將消息投寄的相應的郵箱即可。 5 怎么處理消息是由接收消息的Actor決定的,發送消息Actor可以等待回復,也可以異步處理【類似ajax異步】 6 ActorSystem 的職責是負責創建并管理其創建的 Actor, ActorSystem 是單例的(ActorSystem是一個工廠,專門創建Actor),一個 JVM 進程中有一個即可,而 Acotr 是可以有多個的 7 Actor模型是對并發模型進行了更高的抽象。 8 Actor模型是異步、非阻塞、高性能的事件驅動編程模型 9 Actor模型是輕量級事件處理(1GB 內存可容納百萬級別個 Actor),因此處理大并發性能高.
Actor模型工作機制
1 ActorySystem創建Actor 2 ActorRef:可以理解成是Actor的代理或者引用。 (注:消息是通過ActorRef來發送,而不能通過Actor 發送消息,通過哪個ActorRef 發消息,就表示把該消息發給哪個Actor) 3 消息發送到Dispatcher Message (消息分發器),它得到消息后,會將消息進行分發到對應的MailBox。 (注: Dispatcher Message 可以理解成是一個線程池, MailBox 可以理解成是消息隊列,可以緩沖多個消息,遵守FIFO 先進先出原則) 4 Actor 可以通過 receive方法來獲取消息,然后進行處理。
Actor間傳遞消息機制
1 每一個消息就是一個Message對象。Message 繼承了Runable, 因為Message就是線程類。 2 編程時只需要編寫Actor就可以了,其它的交給Actor模型完成即可。 3 A Actor要給B Actor 發送消息,那么A Actor 要先拿到(也稱為持有) B Actor 的 代理對象ActorRef 才能發送消息 4 每個actor有個mailbox(封裝不可見)且實現了runnable 接口一直在運行,等待其他人給發消息
//1. 當我們繼承Actor后,就是一個Actor,核心方法receive 方法重寫 class HelloActor extends Actor{ //1. receive方法,會被該Actor的MailBox(實現了Runnable接口)調用 //2. 當該Actor的MailBox 接收到消息,就會調用 receive //3. type Receive = PartialFunction[Any, Unit] override def receive: Actor.Receive = { case "hello" => println("收到hello, 回應hello too:)") case "ok" => println("收到ok, 回應ok too:)") case "exit" => { println("接收到exit指令,退出系統") context.stop(self) //停止actoref (停止mailbox) // self 就是自己 context.system.terminate()//退出actorsystem (停止 actor ) } case _ => println("匹配不到") } } object HelloActorDemo{ //先創建一個ActorSystem, 專門用于創建Actor //1. ActorSystem apply方法返回一個 ActorSystem; val actoryFactory = ActorSystem("ActoryFactory") //2. 創建一個Actor的同時,返回Actor的ActorRef 說明 //(1) Props[SayHelloActor] 創建了一個 SayHelloActor實例,使用反射 ,也可以使用 new 方式 // Props[SayHelloActor] 該實例被 ActorSystem 接管了 //(2) "alexHelloActor" 給actor取名 //(3) sayHelloActorRef: ActorRef 就是 Props[SayHelloActor] 的ActorRef //(4) 創建的SayHelloActor(Props[SayHelloActor]) 實例被ActorSystm接管 //(5) ActorRef 僅僅是與SayHelloActor(Props[SayHelloActor]) 關聯起來 private val alexHelloActor1: ActorRef = actoryFactory.actorOf(Props[HelloActor], "alexHelloActor") def main(args: Array[String]): Unit = { alexHelloActor1 ! "hello" alexHelloActor1 ! "ok" alexHelloActor1 ! "exit" } }
Actor自我通訊機制原理圖 當程序執行 aActorRef = actorFactory.actorOf(Props[AActor], "aActor") ,會完成如下任務 1 actorFactory 是 ActorSystem("ActorFactory") 這樣創建的。 2 這里的 Props[AActor] 會使用反射機制,創建一個AActor 對象,如果是actorFactory.actorOf(Props(new AActor(bActorRef)), "aActorRef") 形式,就是使用new 的方式創建一個AActor對象, 注意Props() 是小括號。 3 會創建一個AActor 對象的代理對象 aActorRef , 使用aActorRef 才能發送消息 4 會在底層創建 Dispather Message ,是一個線程池,用于分發消息, 消息是發送到對應的Actor的 MailBox 5 會在底層創建AActor 的MailBox 對象,該對象是一個隊列,可接收Dispatcher Message 發送的消息 6 MailBox 實現了Runnable 接口,是一個線程,一直運行并調用Actor的receive 方法,因此當Dispather 發送消息到MailBox時,Actor 在receive 方法就可以得到信息. 7 aActorRef ! "hello", 表示把hello消息發送到A Actor 的mailbox (通過Dispatcher Message 轉發)
object ActorsGame { def main(args: Array[String]): Unit = { //創建ActorSystem val actorFactory = ActorSystem("actorFactory") // 創建 bobref val bobActoref = actorFactory.actorOf(Props[BobActor], "bobActor") // 創建 alexref val alexActoref = actorFactory.actorOf(Props(new AlexActor(bobActoref)), "alexActor") alexActoref ! "start" } } // 構建 AlexActor 重寫receive時候,傳入bobref ,這樣 alex才能給Bob 發信 class AlexActor (actorref: ActorRef) extends Actor { val bobref: ActorRef = actorref override def receive: Receive = { case "start" => { println("給自己發消息,開始溝通Bob") self ! "hello" } case "hello" => { println("準備給Bob 發消息 ") // 必須持有bobref Thread.sleep(1000) bobref ! "hello Bob san" // 發消息 } case "hello alex san" =>{ println("收到Bob 發的消息") self ! "hello" } } } class BobActor extends Actor { override def receive: Receive = { case "hello Bob san" => { println("接到 alex 發的消息") Thread.sleep(1000) sender() ! "hello alex san" //通過sender() 可以獲取到發現消息的actor的ref } } }
Scala
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。