日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Akka并发编程——第二节:Actor模型(一)

發(fā)布時(shí)間:2024/1/23 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Akka并发编程——第二节:Actor模型(一) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本節(jié)主要內(nèi)容

  • 定義Actor
  • 創(chuàng)建Actor
  • 1. 定義Actor

    通過(guò)擴(kuò)展akka.actor.Actor 特質(zhì)并實(shí)現(xiàn)receive方法來(lái)定義Actor,代碼示例如下

    //通過(guò)擴(kuò)展Actor并實(shí)現(xiàn)receive方法來(lái)定義Actor class MyActor extends Actor {//獲取LoggingAdapter,用于日志輸出val log = Logging(context.system, this)//實(shí)現(xiàn)receive方法,定義Actor的行為邏輯,返回的是一個(gè)偏函數(shù)def receive = {case "test" => log.info("received test")case _ => log.info("received unknown message")}}

    receive方法被定義在Actor當(dāng)中,方法標(biāo)簽如下

    //Actor中的receive方法定義, type Receive = PartialFunction[Any, Unit] def receive: Actor.Receive

    下面給出其完整使用代碼:

    object Example_01 extends App{import akka.actor.Actorimport akka.event.Loggingimport akka.actor.ActorSystemimport akka.actor.Propsclass MyActor extends Actor {val log = Logging(context.system, this)def receive = {case "test" => log.info("received test")case _ => log.info("received unknown message")}}//創(chuàng)建ActorSystem對(duì)象val system = ActorSystem("MyActorSystem")//返回ActorSystem的LoggingAdpaterval systemLog=system.log//創(chuàng)建MyActor,指定actor名稱為myactorval myactor = system.actorOf(Props[MyActor], name = "myactor")systemLog.info("準(zhǔn)備向myactor發(fā)送消息")//向myactor發(fā)送消息myactor!"test"myactor! 123//關(guān)閉ActorSystem,停止程序的運(yùn)行system.shutdown() }

    代碼運(yùn)行結(jié)果:

    [INFO] [04/02/2016 09:29:54.223] [main] [ActorSystem(MyActorSystem)] 準(zhǔn)備向myactor發(fā)送消息 [INFO] [04/02/2016 09:29:54.224] [MyActorSystem-akka.actor.default-dispatcher-3] [akka://MyActorSystem/user/myactor] received test [INFO] [04/02/2016 09:29:54.224] [MyActorSystem-akka.actor.default-dispatcher-3] [akka://MyActorSystem/user/myactor] received unknown message

    輸出“[INFO] [04/02/2016 09:29:54.224] [MyActorSystem-akka.actor.default-dispatcher-3] [akka://MyActorSystem/user/myactor] received test”中的[MyActorSystem-akka.actor.default-dispatcher-3]為對(duì)應(yīng)的線程名,[akka://MyActorSystem/user/myactor]為Actor路徑信息, received test為

    def receive = {case "test" => log.info("received test")case _ => log.info("received unknown message")}

    方法處理后的輸出。關(guān)于[akka://MyActorSystem/user/myactor]路徑信息,將在后續(xù)內(nèi)容中進(jìn)行詳細(xì)闡述。


    也可以通過(guò)混入ActorLogging來(lái)實(shí)現(xiàn)日志功能,具體代碼如下:

    class MyActor extends Actor with ActorLogging{def receive = {case "test" => log.info("received test")case _ => log.info("received unknown message")}}

    ActorLogging的定義如下:

    trait ActorLogging { this: Actor ?private var _log: LoggingAdapter = _def log: LoggingAdapter = {// only used in Actor, i.e. thread safeif (_log eq null)_log = akka.event.Logging(context.system, this)_log}}

    完整代碼如下:

    /**定義Actor時(shí)混入ActorLogging*/ object Example_02 extends App{import akka.actor.Actorimport akka.actor.ActorSystemimport akka.actor.Propsclass MyActor extends Actor with ActorLogging{def receive = {case "test" => log.info("received test")case _ => log.info("received unknown message")}}//創(chuàng)建ActorSystem對(duì)象val system = ActorSystem("MyActorSystem")//返回ActorSystem的LoggingAdpaterval systemLog=system.log//創(chuàng)建MyActor,指定actor名稱為myactorval myactor = system.actorOf(Props[MyActor], name = "myactor")systemLog.info("準(zhǔn)備向myactor發(fā)送消息")//向myactor發(fā)送消息myactor!"test"myactor! 123//關(guān)閉ActorSystem,停止程序的運(yùn)行system.shutdown() }

    代碼運(yùn)行結(jié)果:

    [INFO] [04/02/2016 09:39:21.088] [main] [ActorSystem(MyActorSystem)] 準(zhǔn)備向myactor發(fā)送消息 [INFO] [04/02/2016 09:39:21.089] [MyActorSystem-akka.actor.default-dispatcher-3] [akka://MyActorSystem/user/myactor] received test [INFO] [04/02/2016 09:39:21.089] [MyActorSystem-akka.actor.default-dispatcher-3] [akka://MyActorSystem/user/myactor] received unknown message

    代碼原理與Example_01類似,這里不再贅述。

    2. 創(chuàng)建Actor

    在前面兩個(gè)例子中,通過(guò)

    val myactor = system.actorOf(Props[MyActor], name = "myactor")

    創(chuàng)建Actor,需要注意的是system.actorOf方法返回的是ActorRef對(duì)象,ActorRef為Actor的引用,使用ActorRef對(duì)象可以進(jìn)行消息的發(fā)送等操作。Props為配置對(duì)象,在創(chuàng)建Actor時(shí)使用,它是不可變的對(duì)象,因此它是線程案例且完全可共享的。Akka中創(chuàng)建Actor時(shí),也允許直接傳入MyActor對(duì)象的引用,例如

    //直接通過(guò)new MyActor的方式傳入MyActor對(duì)象的引用,注意這里是Props(new MyActor) val myactor = system.actorOf(Props(new MyActor), name = "myactor")

    但是Akka不推薦這么做,官方文檔給出的解釋是這種方式會(huì)導(dǎo)致不可序列化的Props對(duì)象且可能會(huì)導(dǎo)致競(jìng)爭(zhēng)條件(破壞Actor的封裝性)。另外需要特別注意的是,不允許通過(guò)下列代碼創(chuàng)建Actor

    //下列兩行代碼編譯可以通過(guò),但運(yùn)行時(shí)出拋出異常val myActor=new MyActorval myactor = system.actorOf(Props(myActor), name = "myactor")

    完整運(yùn)行代碼如下:

    /**創(chuàng)建Actor*/ object Example_03 extends App{import akka.actor.Actorimport akka.actor.ActorSystemimport akka.actor.Propsclass MyActor extends Actor with ActorLogging{def receive = {case "test" => log.info("received test")case _ => log.info("received unknown message")}}val system = ActorSystem("MyActorSystem")val systemLog=system.log//下列兩行代碼編譯可以通過(guò),但運(yùn)行時(shí)出拋出異常val myActor=new MyActorval myactor = system.actorOf(Props(myActor), name = "myactor")systemLog.info("準(zhǔn)備向myactor發(fā)送消息")//向myactor發(fā)送消息myactor!"test"myactor! 123//關(guān)閉ActorSystem,停止程序的運(yùn)行system.shutdown() }

    運(yùn)行結(jié)果如下:

    Exception in thread "main" akka.actor.ActorInitializationException: You cannot create an instance of [chapter02.Example_03$MyActor] explicitly using the constructor (new). You have to use one of the 'actorOf' factory methods to create a new actor. See the documentation.at akka.actor.ActorInitializationException$.apply(Actor.scala:167)at akka.actor.Actor$class.$init$(Actor.scala:423)at chapter02.Example_03$MyActor.<init>(MyActor.scala:73)at chapter02.Example_03$delayedInit$body.apply(MyActor.scala:84)at scala.Function0$class.apply$mcV$sp(Function0.scala:40)at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)at scala.App$$anonfun$main$1.apply(App.scala:71)at scala.App$$anonfun$main$1.apply(App.scala:71)at scala.collection.immutable.List.foreach(List.scala:318)at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:32)at scala.App$class.main(App.scala:71)at chapter02.Example_03$.main(MyActor.scala:68)at chapter02.Example_03.main(MyActor.scala)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:606)at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

    從“You cannot create an instance of [chapter02.Example_03$MyActor] explicitly using the constructor (new). You have to use one of the ‘a(chǎn)ctorOf’ factory methods to create a new actor.”可以看到,不能通過(guò)顯式地調(diào)用構(gòu)造函數(shù)創(chuàng)建Actor,只能使用actorOf工廠方法創(chuàng)建Actor。

    下面介紹2種在實(shí)際中經(jīng)常使用的Actor創(chuàng)建方法
    (1)調(diào)用system.actorOf創(chuàng)建Actor

    val system = ActorSystem("mySystem") val myActor = system.actorOf(Props[MyActor], "myactor2")

    完整代碼在Example_01、Example_02中已經(jīng)演示過(guò)了,這里需要說(shuō)明的是通過(guò)system.actorOf工廠方法創(chuàng)建的Actor為頂級(jí)Actor

    在Akka框架中,每個(gè)Akka應(yīng)用程序都會(huì)有一個(gè)守衛(wèi)Actor,名稱為user,所有通過(guò)system.actorOf工廠方法創(chuàng)建的Actor都為user的子Actor,也是整個(gè)Akka程序的頂級(jí)Actor。

    (2)調(diào)用context.actorOf創(chuàng)建Actor
    完整代碼如下:

    /**創(chuàng)建Actor,調(diào)用context.actorOf方法*/ object Example_04 extends App{import akka.actor.Actorimport akka.actor.ActorSystemimport akka.actor.Propsclass FirstActor extends Actor with ActorLogging{//通過(guò)context.actorOf方法創(chuàng)建Actorval child = context.actorOf(Props[MyActor], name = "myChild")def receive = {case x => child ! x;log.info("received "+x)}}class MyActor extends Actor with ActorLogging{def receive = {case "test" => log.info("received test")case _ => log.info("received unknown message")}}val system = ActorSystem("MyActorSystem")val systemLog=system.log//創(chuàng)建FirstActor對(duì)象val myactor = system.actorOf(Props[FirstActor], name = "firstActor")systemLog.info("準(zhǔn)備向myactor發(fā)送消息")//向myactor發(fā)送消息myactor!"test"myactor! 123Thread.sleep(5000)//關(guān)閉ActorSystem,停止程序的運(yùn)行system.shutdown() }
    • 1

    代碼運(yùn)行結(jié)果

    [INFO] [04/02/2016 15:05:34.770] [main] [ActorSystem(MyActorSystem)] 準(zhǔn)備向myactor發(fā)送消息 [INFO] [04/02/2016 15:05:34.771] [MyActorSystem-akka.actor.default-dispatcher-3] [akka://MyActorSystem/user/firstActor/myChild] received test [INFO] [04/02/2016 15:05:34.771] [MyActorSystem-akka.actor.default-dispatcher-2] [akka://MyActorSystem/user/firstActor] received test [INFO] [04/02/2016 15:05:34.771] [MyActorSystem-akka.actor.default-dispatcher-2] [akka://MyActorSystem/user/firstActor] received 123 [INFO] [04/02/2016 15:05:34.771] [MyActorSystem-akka.actor.default-dispatcher-3] [akka://MyActorSystem/user/firstActor/myChild] received unknown message

    通過(guò)代碼的運(yùn)行結(jié)果可以看到,FirstActor的Actor路徑信息為akka://MyActorSystem/user/firstActor,而通過(guò)

    class FirstActor extends Actor with ActorLogging{//通過(guò)context.actorOf方法創(chuàng)建Actorval child = context.actorOf(Props[MyActor], name = "myChild")def receive = {case x => child ! x;log.info("received "+x)}}

    代碼使用context.actorOf創(chuàng)建的MyActor,其Actor路徑信息為[akka://MyActorSystem/user/firstActor/myChild],這意味著mychild為firstActor的子Actor,層次結(jié)構(gòu)如下圖所示

    也就是說(shuō)context.actorOf和system.actorOf的差別是system.actorOf創(chuàng)建的actor為頂級(jí)Actor,而context.actorOf方法創(chuàng)建的actor為調(diào)用該方法的Actor的子Actor

    總結(jié)

    以上是生活随笔為你收集整理的Akka并发编程——第二节:Actor模型(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。