Akka并发编程——3、Actor模型(三)
来源:互联网 发布:单片机上位机编程 编辑:程序博客网 时间:2024/06/01 10:47
摘要: 本将主要内容: 1. Actor引用、Actor路径
1. Actor引用、Actor路径:下图是Akka官方文档中给出的一张图 该图清晰地说明了ActorPath,ActorRef,Actor及ActorSystem之间的关系,并说明了Actor整体的层次结构。前面我们提到,Akka应用程序会持有一个名称为user的Actor,该Actor被称为guardian supervisor(守护监督器,参见Akka系列的第一篇文章)
本将主要内容:
Actor引用(ActorRef)、Actor路径(ActorPath)
Actor引用、Actor路径
上图是Akka官方给的一张图,该图清晰地说明了ActorPath,ActorRef,Actor及ActorSystem之间的关系,并说明了Actor整体的层次结构(ActorRef等具体可参见Akka系列的第一篇文章)。前面我们提到,Akka应用程序会持有一个名称为user的Actor,该Actor被称为guardian supervisor(守卫监督器),无论是ActorSystem创建的Actor还是通过ActorContext创建的Actor都为user的子类,user是Daemon Actor。
(一)ActorRef
对于ActorRef,我们已经很熟悉了,通过调用ActorSystem.actorOf方法可以创建Actor,返回的便是ActorRef,例如代码:返回的便是名为FirstActor的ActorRef对象。ActorRef最重要的作用便是向Actor发送消息,例如:
另外,还可以通过context隐式对象获取父Actor和子Actor的ActorRef,示例代码如下:
/**Actor API:成员变量self及sender()方法的使用*/object Example_07 extends App{ import akka.actor.Actor import akka.actor.ActorSystem import akka.actor.Props class FirstActor extends Actor with ActorLogging{ //通过context.actorOf方法创建Actor var child:ActorRef = _ override def preStart(): Unit ={ log.info("preStart() in FirstActor") //通过context上下文创建Actor child = context.actorOf(Props[MyActor], name = "myActor") } def receive = { //向MyActor发送消息 case x => child ! x;log.info("received "+x) } } class MyActor extends Actor with ActorLogging{ var parentActorRef:ActorRef=_ override def preStart(): Unit ={ //通过context.parent获取其父Actor的ActorRef parentActorRef=context.parent } def receive = {
case "test" => log.info("received test");parentActorRef!"message from ParentActorRef" // 应该是ChildActorRef,后面截图倒数第二个提示也应该相应改变。因为是从子Actor发送的消息。 case _ => log.info("received unknown message"); } } val system = ActorSystem("MyActorSystem") val systemLog=system.log //创建FirstActor对象 val myactor = system.actorOf(Props[FirstActor], name = "firstActor") //获取ActorPath val myActorPath=system.child("firstActor") //通过system.actorSelection方法获取ActorRef val myActor1=system.actorSelection(myActorPath) systemLog.info("准备向myactor发送消息") //向myActor1发送消息 myActor1!"test" myActor1! 123 Thread.sleep(5000) //关闭ActorSystem,停止程序的运行 system.shutdown()}代码运行结果
代码
红色部分,通过context隐式的获取MyActor的父Actor的ActorRef,本例为FirstActor,因为:
通过context.actorOf工厂方法创建的Actor为此Actor的子Actor,即FirstActor成为了MyActor的supervisor。
即当MyActor接受到test消息的时候,向其parent actor(FirstActor)发送消息“message from ParentActorRef”。
现在,让我们来总结一下获取ActorRef的方法:
(1)通过ActorSystem的actorOf方法,不过这种方式是通过创建顶级Actor,然后返回其ActorRef
(2)通过context.actorOf方法,这种方式也是通过创建Actor,然后返回其ActorRef
(3)通过context.parent、context.self、context.children方法获取当前Actor的父Actor、当前Actor及子Actor的ActorRef,这种方式是获取已经创建好的Actor的ActorRef
(4)通过val myActor1=system.actorSelection(myActorPath)方法代码运行结果:来获取myActor的ActorRef,这种方式也是获取已经创建好的Actor的ActorRef
(二)ActorPath
在前面的例子中,我们通过已经使用到了ActorPath。在Akka中,ActorPath采用统一资源定位符(URL)的方式进行组织,例如
本地ActorPath是Akka并发编程中的ActorPath表示方式,而远程ActorPath是Akka分布式编程中常用的ActorPath表示方式,”akka.tcp://my-sys@host.example.com:5678/user/service-b”中的TCP表示使用的是TCP协议,也可以使用UDP协议,使用UDP协议的远程ActorPath表示方式有如下形式:(即只改变红色部分)
其中:akka.udp表示的是使用的协议,my-sys表示的是ActorSytem名称(由下面语句创建
val system = ActorSystem("MyActorSystem")),host.example.com:5678为远程机器地址及端口,user为guardian supervisor,service-b为当前应用程序的顶级Actor(通过system.actorOf方法创建的)
/**ActorPath*/object Example_08 extends App{ import akka.actor.Actor import akka.actor.ActorSystem import akka.actor.Props class FirstActor extends Actor with ActorLogging{ //通过context.actorOf方法创建Actor var child:ActorRef = _ override def preStart(): Unit ={ log.info("preStart() in FirstActor") //通过context上下文创建Actor child = context.actorOf(Props[MyActor], name = "myActor") } def receive = { //向MyActor发送消息 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 //创建FirstActor对象 val firstactor = system.actorOf(Props[FirstActor], name = "firstActor") //获取ActorPath val firstActorPath=system.child("firstActor") systemLog.info("firstActorPath--->{}",firstActorPath) //通过system.actorSelection方法获取ActorRef val myActor1=system.actorSelection(firstActorPath) //直接指定其路径 val myActor2=system.actorSelection("/user/firstActor") //使用相对路径 val myActor3=system.actorSelection("../firstActor") systemLog.info("准备向myactor发送消息") //向myActor1发送消息 myActor2!"test" myActor2! 123 Thread.sleep(5000) //关闭ActorSystem,停止程序的运行 system.shutdown()}代码运行结果:
本例中的重点如下:
通过 val firstActorPath=system.child(“firstActor”)得到firstActor的ActorPath(完整路径),然后使用下面的三种方式可以获得其ActorRef(1、完整路径 2、绝对路径 3、相对路径)
注意:绝对路径使用的是/guardian supevisor/Actor,即/user/firstActor的这种方式。
同样,如果我们想获取myActor,则方法是类似的:
关于远程ActorRef的获取,我们将在后续章节中进行讲述。
- Akka并发编程——3、Actor模型(三)
- Akka并发编程——1、Actor模型(一)
- Akka并发编程——2、Actor模型(二)
- Akka并发编程——4、Actor模型(四)
- Akka并发编程——5、Actor模型(五)
- Akka并发编程——第四节:Actor模型(三)
- Akka并发编程——第四节:Actor模型(三)
- Akka并发编程——第五节:Actor模型(四) 停止Actor
- Akka并发编程——第二节:Actor模型(一)
- Akka并发编程——第三节:Actor模型(二)
- Akka并发编程——第五节:Actor模型(四)
- Akka并发编程——第六节:Actor模型(五)
- Akka并发编程——第七节:Actor模型(六)
- Akka并发编程——第八节:Actor模型(七)
- Akka并发编程——第二节:Actor模型(一)
- Akka并发编程——第三节:Actor模型(二)
- Akka并发编程——第六节:Actor模型(五)
- Akka并发编程——第七节:Actor模型(六)
- spring boot(3)-Rest风格接口
- Android RSA加解密
- Google关于GFS(Google File System)技术论文中文版
- linux命令行的软件推荐
- 检测内存泄露:Instruments中的Leaks
- Akka并发编程——3、Actor模型(三)
- 《深入探索C++对象模型》读后总结
- Ajax技术之Ajax重构(封装XMLHttpRequest)
- 强化学习入门学习记录
- WAMPServer多站点配置
- Python 3基础教程19-模块导入语法
- 机器学习----回归问题
- C++复习0.1——三目/const/重载/类和对象
- 基于内置锁的生产者消费者模型