Akka并发编程——第六节:Actor模型(五)
来源:互联网 发布:主流数据库 对比 编辑:程序博客网 时间:2024/06/08 18:08
本章主要内容:
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.Actor import akka.actor.Props import akka.event.Logging import 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发送消息,隐式地传递sender case Start(msg) => other ! msg //使用fire-and-forget消息模型向OtherActor发送消息,直接调用tell方法,显式指定sender case 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") //创建ContextActor val exampleActor = system.actorOf(Props[ExampleActor],name="ExampleActor") //使用fire-and-forget消息模型向exampleActor发送消息 exampleActor!Run("Running") exampleActor!Start("Starting") //关闭ActorSystem system.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发送消息,隐式地传递sender case Start(msg) => other ! msg //使用fire-and-forget消息模型向OtherActor发送消息,直接调用tell方法,显式指定sender case 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.Actor import akka.actor.Props import akka.event.Logging import akka.actor.ActorSystem import scala.concurrent.Future import akka.pattern.ask import akka.util.Timeout import scala.concurrent.duration._ import akka.pattern.pipe import 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) //基础信息对应Actor class 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") } } //兴趣爱好对应Actor class 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完整信息对应Actor class 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结果发送给PersonActor pipe(combineResult).to(personActor) } } val _system = ActorSystem("Send-And-Receive-Future") val combineActor = _system.actorOf(Props[CombineActor],name="CombineActor") combineActor ! 12345 Thread.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模型(五)
- Akka并发编程——第六节:Actor模型(五)
- Akka并发编程——5、Actor模型(五)
- Akka并发编程——1、Actor模型(一)
- Akka并发编程——2、Actor模型(二)
- Akka并发编程——3、Actor模型(三)
- Akka并发编程——4、Actor模型(四)
- Akka并发编程——第五节:Actor模型(四) 停止Actor
- Akka并发编程——第二节:Actor模型(一)
- Akka并发编程——第四节:Actor模型(三)
- Akka并发编程——第七节:Actor模型(六)
- Akka并发编程——第二节:Actor模型(一)
- Akka并发编程——第四节:Actor模型(三)
- Akka并发编程——第七节:Actor模型(六)
- Akka并发编程——第三节:Actor模型(二)
- Akka并发编程——第五节:Actor模型(四)
- Akka并发编程——第八节:Actor模型(七)
- Akka并发编程——第三节:Actor模型(二)
- 数据结构基础五-----《线性结构的两种常见应用之一 队列》
- 4-11固定定位的用途返回顶部按钮
- Angular4+NodeJs+MySQL 入门-01
- pl/sql oraclev_name|| 判断 循环 语句
- PHP RES加密如何避免密文过长和乱码
- Akka并发编程——第六节:Actor模型(五)
- 索引
- linux下安装tomcat
- Python 了解 类中方法的方式
- 自主编程实现选择,冒泡,快速,归并,希尔排序
- 基于栈的非递归方法实现二叉树
- 《具身认知》
- synchronized锁优化
- jdk动态代理生成代理对象源码分析-4