<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ### 引言 這篇文章主要是第一次學習Akka編程,先試試水,探探坑,對Akka和SBT的使用有一個直觀的了解,以幾個簡單的akka編程實例來說明akka的使用。希望在日后的學習和編程中,能有更多自己的體會和經驗總結來分享。 ### Actor模型 Actor實例可以想象成是服務器上的Web服務,你無法控制,只能通過發送消息去請求執行任務或查詢信息,而不能直接在Web服務中修改狀態或者處理資源。通過發送不可改變的消息,雖然看上去有些限制,但是可以很簡單安全的編寫并發程序。 ### Actor系統的形象理解 一個actor是基于Actor系統的最小單元,就像面向對象系統中的對象實例一樣,它也封裝了狀態和行為。我們無法窺探actor內部的信息,只能通過發送消息來請求狀態信息(就像是問一個人,他感覺如何)。actor中有一個存放不可變狀態信息的信箱。我們通過發送信息和actor進行通信,當actor收到信息之后,它會運用相關算法來處理具體的信息。 在一個應用程序中,多個actor構成了一套層級系統,像是一個家族或者一個商業組織。一個actor可以認為是一個商業組織的個人。一個actor有一個父親,稱為監督者(supervisor),還有好多孩子,可以認為,在一個商業組織中,主席(actor)下面有多個副主席,副主席也有很多下屬隨從。 Actor系統的最佳實踐是“**委派任務**”,尤其是當actor的行為被阻塞的時候。可以想象,在實際商業活動中,主席將要做的工作分配給下面的幾個副主席去分別執行,而副主席也會將子任務分配給自己的隨從,直到該任務被下屬們執行完畢。 ### 處理故障 Actor模型的一個重要內容是處理故障。在工作工程中,如果出現錯誤或者拋出異常,actor和其子actor都將暫停,然后發送一條信息給監督者(supervisor)actor,報告出現故障的信號。 根據工作任務和故障的性質,監督者actor將會作出幾種選擇: > - 恢復下屬actor,保留內部狀態 > - 重啟下屬actor,清空狀態 > - 終止下屬actor > - 上報故障 ### Hello,Actor實例 現在我用一個最簡單的actor編程實例來介紹akka編程,先給出代碼: ~~~ import akka.actor.Actor import akka.actor.ActorSystem import akka.actor.Props class HelloActor extends Actor{ def receive = { case "hello" => println("hello back to you.") case _ => println("huh?") } } object Test1_HelloActor extends App { // actor need an ActorSystem val system = ActorSystem("HelloSystem") // create and start the actor val helloActor = system.actorOf(Props[HelloActor], name="helloActor") // send two messages helloActor ! "hello" helloActor ! "what" // shutdown the actor system system.shutdown } ~~~ 代碼注解: > - Actor由HelloActor定義 > - HelloActor的行為有receive方法定義實現,其中使用了模式匹配表達式 > - HelloActor接收字符串`hello`作為消息,做出相應打印動作 > - Test1_HelloActor的object用來測試actor > - ActorSystem接收一個name參數,并且通過`system.actorOf`創建actor實例 > - 創建Actor實例名為helloActor,其構造函數沒有參數 > - Actor創建后自動運行,不需調用start或者run方法 > - 通過`!`方法來發送消息 ### ActorSystem 一個actor system是actors的層級集團,分享公共配置信息(比如分發器dispatchers,部署deployments,遠程功能remote capabilities,地址addresses)。它同時也是創建和查詢actors的入口。ActorSystem是為你的應用程序分配線程資源的結構。 ### ActorRef 當你調用`ActorSystem`的`actorOf`方法時,將創建并返回一個`ActorRef`的實例: `def actorOf(props: Props, name: String): ActorRef`。 這個引用用來處理actor,你可以將其看做是處理實際actor的代理人(broker)或包裝外觀(facade)。ActorRef防止你破壞Actor模型,比如直接處理Actor實例,或直接修改Actor實例中的變量。所以只能通過給actor發送消息方式來執行任務,這種“袖手旁觀(不干涉,hands-off)”的方法幫助鞏固適宜的編程實踐。 ActorRef有以下特點: > - 它是不可變的 > - 它與actor實體是一對一的關系 > - 它是可序列化的,網絡可感知的。這使得你可以在網絡環境中傳送一個ActorRef ### Actor之間的通信實例 下面給出的是兩個actor實例相互發送消息進行通信的PingPong示例: ~~~ import akka.actor._ case object PingMessage case object PongMessage case object StartMessage case object StopMessage class Ping(pong: ActorRef) extends Actor{ var count = 0 def incrementAndPrint {count += 1; println(s"$count:ping")} def receive = { case StartMessage => incrementAndPrint pong ! PongMessage case PingMessage => incrementAndPrint if(count > 99) { sender ! StopMessage println("ping stopped") context.stop(self) } else sender ! PongMessage case _ => println("Ping got unexpected information") } } class Pong extends Actor { var count = 0 def receive = { case StopMessage => println("pong stopped") context.stop(self) case PongMessage => count += 1 println(s"$count:pong") sender ! PingMessage case _ => println("Pong got unexpected information") } } object PingPangTest extends App{ val system = ActorSystem("PingPongTest") val pongActor = system.actorOf(Props[Pong], name="pong") val pingActor = system.actorOf(Props(new Ping(pongActor)), name = "ping") pingActor ! StartMessage } ~~~ 代碼注釋: > - 創建`ActorSystem`之后; > - 創建`Pong`的actor實例(pongActor對象其實是`ActorRef`的實例); > - 之后創建`Ping`的actor實例,其構造函數接受`ActorRef`參數; > - 通過給`pingActor`發送一個`StartMessage`消息來啟動pingActor和pongActor的具體動作; > - `Ping` Actor和`Pong` Actor通過PingMessage和PongMessage相互發送消息,`sender`用來引用消息發送源Actor; > - `Ping`通過計數,知道進行了100次消息的發送之后,發送StopMessage來終止actor。分別調用自己的`context.stop`方法來結束 ### 啟動Actor 在ActorSystem層面,通過調用`system.actorOf`方法來創建actors;在actor內部,通過調用`context.actorOf`方法來創建子actor。 下面給出一個ParentChild示例: ~~~ import akka.actor._ case class CreateChild (name: String) case class Name (name: String) class Child extends Actor { var name = "No name" override def postStop: Unit = { println(s"D'oh! They killed me ($name): ${self.path}") } def receive = { case Name(name) => this.name = name case _ => println(s"Child $name got message.") } } class Parent extends Actor { def receive = { case CreateChild(name) => // Parent creates a new Child here println(s"Parent about to create Child ($name) ...") val child = context.actorOf(Props[Child], name=s"$name") child ! Name(name) case _ => println(s"Parent got some other message.") } } object ParentChildDemo extends App{ val actorSystem = ActorSystem("ParentChildTest") val parent = actorSystem.actorOf(Props[Parent], name="Parent") // send messages to Parent to create to child actors parent ! CreateChild("XiaoMing") parent ! CreateChild("XiaoLiang") Thread.sleep(500) // lookup XiaoMing, the kill it println("Sending XiaoMing a PoisonPill ... ") val xiaoming = actorSystem.actorSelection("/user/Parent/XiaoMing") xiaoming ! PoisonPill println("XiaoMing was killed") Thread.sleep(5000) actorSystem.shutdown } ~~~ 打印結果: ~~~ Parent about to create Child (XiaoMing) ... Parent about to create Child (XiaoLiang) ... Sending XiaoMing a PoisonPill ... XiaoMing was killed D'oh! They killed me (XiaoMing): akka://ParentChildTest/user/Parent/XiaoMing D'oh! They killed me (XiaoLiang): akka://ParentChildTest/user/Parent/XiaoLiang ~~~ ### 終止Actor 在ActorSystem層面,通過`system.stop(actorRef)`來終止一個actor;在actor內部,使用`context.stop(actorRef)`來結束一個actor。 如果當前有正在處理的消息,對該消息的處理將在actor被終止之前完成,但是郵箱中的后續消息將不會被處理。缺省情況下這些消息會被送到 ActorSystem的`dead letter mailbox`, 但是這取決于郵箱的實現。 ### actor終止的相關處理 actor的終止分兩步: 第一步actor將停止對郵箱的處理,向所有子actor發送終止命令,然后處理來自子actor的終止消息直到所有的子actor都完成終止, 最后終止自己(調用postStop,銷毀郵箱,向DeathWatch發布Terminated,通知其監管者)。這個過程保證actor系統中的子樹以一種有序的方式終止,將終止命令傳播到葉子結點并收集它們回送的確認消息給被終止的監管者。如果其中某個actor沒有響應(i.e.由于處理消息用了太長時間以至于沒有收到終止命令), 整個過程將會被阻塞。 在 ActorSystem.shutdown被調用時, 系統根監管actor會被終止,以上的過程將保證整個系統的正確終止。 `postStop()` hook是在actor被完全終止以后調用的。這是為了清理資源: ~~~ override def postStop() = { // 關閉文件或數據庫連接 } ~~~ ### PoisonPill和gracefulStop 還有其他兩種方式,發送`PoisonPill`消息或者使用`gracefulStop`終止。 你也可以向actor發送`akka.actor.PoisonPill`消息,這個消息處理完成后actor會被終止。PoisonPill與普通消息一樣被放進隊列,因此會在已經入隊列的其它消息之后被執行。 如果你想等待終止過程的結束,或者組合若干actor的終止次序,可以使用gracefulStop。 下面給出gracefulStop的代碼示例: ~~~ import akka.actor._ import akka.pattern.gracefulStop import scala.concurrent.{Await, ExecutionContext, Future} import scala.concurrent.duration._ import scala.language.postfixOps case object TestActorStop class TestActor extends Actor { def receive = { case TestActorStop => context.stop(self) case _ => println("TestActor got message") } override def postStop {println("TestActor: postStop")} } object GracefulStopTest extends App{ val system = ActorSystem("GracefulStopTest") val testActor = system.actorOf(Props[TestActor], name="TestActor") // try to stop the actor graceful try { val stopped: Future[Boolean] = gracefulStop(testActor, 2 seconds, TestActorStop) Await.result(stopped, 3 seconds) println("testActor was stopped") } catch { case e: akka.pattern.AskTimeoutException => e.printStackTrace } finally { system.shutdown } } ~~~ `gracefulStop(actorRef, timeout)`將返回一個Future實例,當目標actor有處理相關終止動作的消息時,會執行成功。 上面示例中,通過發送TestActorStop消息來終止actor;如果沒有處理終止的工作,當超過2s后,Future拋出`akka.pattern.AskTimeoutException`異常。默認情況下,gracefulStop將發送PoisonPill消息。 ### Kill消息 當深入Akka actors,我們將認識監督者策略(supervisor strategies)概念。當實現了監督者策略,向actor發送一個`Kill`消息,這可以用來重新啟動actor。如果使用默認的監督者策略,Kill消息將終止目標actor。 下面是示例代碼: ~~~ import akka.actor._ class Number5 extends Actor { def receive = { case _ => println("Number 5 got a message") } override def preStart { println("Number 5 is alive")} override def postStop { println("Number 5::postStop called")} override def preRestart(reason: Throwable, message: Option[Any]): Unit = { println("Number 5::preRestart called") } override def postRestart(reason: Throwable): Unit = { println("Number 5::postRestart called") } } object KillTest extends App{ val system = ActorSystem("KillTestSystem") val number5 = system.actorOf(Props[Number5], name="Number5") number5 ! "hello" number5 ! Kill system.shutdown } ~~~ 打印的信息: ~~~ Number 5 is alive Number 5 got a message [ERROR] [01/17/2016 19:20:09.342] [KillTestSystem-akka.actor.default-dispatcher-3] [akka://KillTestSystem/user/Number5] Kill (akka.actor.ActorKilledException) Number 5::postStop called ~~~ **轉載請注明作者Jason Ding及其出處** [Github博客主頁(http://jasonding1354.github.io/)](http://jasonding1354.github.io/) [GitCafe博客主頁(http://jasonding1354.gitcafe.io/)](http://jasonding1354.gitcafe.io/) [CSDN博客(http://blog.csdn.net/jasonding1354)](http://blog.csdn.net/jasonding1354) [簡書主頁(http://www.jianshu.com/users/2bd9b48f6ea8/latest_articles)](http://www.jianshu.com/users/2bd9b48f6ea8/latest_articles) **Google搜索jasonding1354進入我的博客主頁**
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看