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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Akka并发编程——第六节:Actor模型(五)

發布時間:2024/1/23 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Akka并发编程——第六节:Actor模型(五) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本章主要內容:
1. !消息發送,Fire-and-Forget消息模型
2. ?消息發送,Send-And-Receive-Future消息模型

Akka提供了兩種消息模型:fire-and-forget和Send-And-Receive-Future。fire-and-forget是一種單向消息發送模型,指的是異步發送消息,通過異步發送消息且消息發送后可以立即返回,Akka中使用?方法進行fire-and-forget消息發送,如stringActor!”Creating Actors with implicit val context”,它的意思是當前發送方Aactor向stringActor發送字符串消息”Creating Actors with implicit val context”,發送完該消息后立即返回,而無需等待stringActor的返回,!還有個重載的方法tell;Send-And-Receive-Future指的是異步發送消息則是一種雙向消息發送模型,向目標Actor發送完消息后,然后返回一個Future作為后期可能的返回,當前發送方Actor將等待目標Actor的返回,Akka中使用?方法進行Send-And-Receive-Future消息的發送,它也同樣有一個重載的方法ask

1. !消息發送,Fire-and-Forget消息模型

/*** 消息處理:!(Fire-Forget)*/ object Example12 extends App{import akka.actor.Actorimport akka.actor.Propsimport akka.event.Loggingimport akka.actor.ActorSystem//定義幾種不同的消息case class Start(var msg:String)case class Run(var msg:String)case class Stop(var msg:String)class ExampleActor extends Actor {val other = context.actorOf(Props[OtherActor], "OtherActor")val log = Logging(context.system, this)def receive={//使用fire-and-forget消息模型向OtherActor發送消息,隱式地傳遞sendercase Start(msg) => other ! msg//使用fire-and-forget消息模型向OtherActor發送消息,直接調用tell方法,顯式指定sendercase Run(msg) => other.tell(msg, sender)}}class OtherActor extends Actor{val log = Logging(context.system, this)def receive ={case s:String=>log.info("received message:\n"+s)case _ ? log.info("received unknown message")}}//創建ActorSystem,ActorSystem為創建和查找Actor的入口//ActorSystem管理的Actor共享配置信息如分發器(dispatchers)、部署(deployments)等val system = ActorSystem("MessageProcessingSystem")//創建ContextActorval exampleActor = system.actorOf(Props[ExampleActor],name="ExampleActor")//使用fire-and-forget消息模型向exampleActor發送消息exampleActor!Run("Running")exampleActor!Start("Starting")//關閉ActorSystemsystem.shutdown() }

代碼運行結果如下:

[INFO] [03/20/2016 20:57:43.665] [MessageProcessingSystem-akka.actor.default-dispatcher-5] [akka://MessageProcessingSystem/user/ExampleActor/OtherActor] received message: Running [INFO] [03/20/2016 20:57:43.672] [MessageProcessingSystem-akka.actor.default-dispatcher-5] [akka://MessageProcessingSystem/user/ExampleActor/OtherActor] received message: Starting

在ExampleActor中,通過隱式變量context創建了OtherActor實例:val other = context.actorOf(Props[OtherActor], “OtherActor”),在ExampleActor的receive方法中,處理兩種不同類型的消息例如:

//使用fire-and-forget消息模型向OtherActor發送消息,隱式地傳遞sendercase Start(msg) => other ! msg//使用fire-and-forget消息模型向OtherActor發送消息,直接調用tell方法,顯式指定sendercase Run(msg) => other.tell(msg, sender)
  • 1

處理Start類型的消息時,直接使用!進行消息發送,而處理Run類型的消息時,使用的是tell方法,可以看到使用tell方法需要顯式地指定其sender,而使用!進行消息發送則不需要,事實上!方法通過隱式值傳入需要的Sender,對比!與tell方法的定義便很容易理解

//!方法的定義 def !(message: Any)(implicit sender: ActorRef = Actor.noSender): Unit //tell方法的定義 final def tell(msg: Any, sender: ActorRef): Unit = this.!(msg)(sender)

可以看到,tell方法的實現依賴于!方法。如果在一個Actor當中使用!方法時,例如ExampleActor中使用的other ! msg向OtherActor發送消息,則sender隱式為ExampleActor,如果不是在Actor中使用則默認為Actor.noSender,即sender為null。

2. ?消息發送,Send-And-Receive-Future消息模型

理解了Fire-And-Forget消息模型后,接著對Send-And-Receive-Future消息模型進行介紹,下面的代碼給出了其使用示例。

/*** 消息處理:?(Send-And-Receive-Future)*/ object Example13 extends App{import akka.actor.Actorimport akka.actor.Propsimport akka.event.Loggingimport akka.actor.ActorSystemimport scala.concurrent.Futureimport akka.pattern.askimport akka.util.Timeoutimport scala.concurrent.duration._import akka.pattern.pipeimport scala.concurrent.ExecutionContext.Implicits.global//消息:個人基礎信息case class BasicInfo(id:Int,val name:String, age:Int)//消息:個人興趣信息case class InterestInfo(id:Int,val interest:String)//消息: 完整個人信息case class Person(basicInfo: BasicInfo,interestInfo: InterestInfo)//基礎信息對應Actorclass BasicInfoActor extends Actor{val log = Logging(context.system, this)def receive = {//處理送而來的用戶ID,然后將結果發送給sender(本例中對應CombineActor)case id:Int ?log.info("id="+id);sender!new BasicInfo(id,"John",19)case _ ? log.info("received unknown message")}}//興趣愛好對應Actorclass InterestInfoActor extends Actor{val log = Logging(context.system, this)def receive = {//處理發送而來的用戶ID,然后將結果發送給sender(本例中對應CombineActor)case id:Int ?log.info("id="+id);sender!new InterestInfo(id,"足球")case _ ? log.info("received unknown message")}}//Person完整信息對應Actorclass PersonActor extends Actor{val log = Logging(context.system, this)def receive = {case person: Person =>log.info("Person="+person)case _ ? log.info("received unknown message")}}class CombineActor extends Actor{implicit val timeout = Timeout(5 seconds)val basicInfoActor = context.actorOf(Props[BasicInfoActor],name="BasicInfoActor")val interestInfoActor = context.actorOf(Props[InterestInfoActor],name="InterestInfoActor")val personActor = context.actorOf(Props[PersonActor],name="PersonActor")def receive = {case id: Int =>val combineResult: Future[Person] =for {//向basicInfoActor發送Send-And-Receive-Future消息,mapTo方法將返回結果映射為BasicInfo類型basicInfo <- ask(basicInfoActor, id).mapTo[BasicInfo]//向interestInfoActor發送Send-And-Receive-Future消息,mapTo方法將返回結果映射為InterestInfo類型interestInfo <- ask(interestInfoActor, id).mapTo[InterestInfo]} yield Person(basicInfo, interestInfo)//將Future結果發送給PersonActorpipe(combineResult).to(personActor)}}val _system = ActorSystem("Send-And-Receive-Future")val combineActor = _system.actorOf(Props[CombineActor],name="CombineActor")combineActor ! 12345Thread.sleep(5000)_system.shutdown}

代碼運行結果如下:

[INFO] [03/20/2016 22:55:11.208] [Send-And-Receive-Future-akka.actor.default-dispatcher-3] [akka://Send-And-Receive-Future/user/CombineActor/BasicInfoActor] id=12345 [INFO] [03/20/2016 22:55:11.220] [Send-And-Receive-Future-akka.actor.default-dispatcher-2] [akka://Send-And-Receive-Future/user/CombineActor/InterestInfoActor] id=12345 [INFO] [03/20/2016 22:55:11.223] [Send-And-Receive-Future-akka.actor.default-dispatcher-4] [akka://Send-And-Receive-Future/user/CombineActor/PersonActor] Person=Person(BasicInfo(12345,John,19),InterestInfo(12345,足球))
  • 1

代碼中定義了3種類型的消息,分別是個人基礎信息case class BasicInfo(id:Int,val name:String, age:Int)、個人興趣信息case class InterestInfo(id:Int,val interest:String)以及完整個人信息case class Person(basicInfo: BasicInfo,interestInfo: InterestInfo),然后為這3種類型的消息定義了相應的Actor即BasicInfoActor、InterestInfoActor和PersonActor,在CombineActor分別創建相應Actor的實例,receive方法中使用ask向BasicInfoActor、InterestInfoActor發送Send-And-Receive-Future模型消息,BasicInfoActor、InterestInfoActor中的receive方法接收到發送來的Int類型消息并分別使用!向CombineActor發送BasicInfo、InterestInfo消息,將結果保存在Future[Person]中,然后通過代碼pipe(combineResult).to(personActor)將結果發送給PersonActor。

總結

以上是生活随笔為你收集整理的Akka并发编程——第六节:Actor模型(五)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。