Actor 模型快速入门案例 | 学习笔记

简介: 快速学习 Actor 模型快速入门案例

开发者学堂课程【Scala 核心编程 - 进阶Actor 模型快速入门案例学习笔记,与课程紧密连接,让用户快速学习知识。

课程地址https://developer.aliyun.com/learning/course/610/detail/9115


Actor 模型快速入门案例


内容介绍:

一、Actor 模型工作机制说明(复习)

二、应用实例需求

三、SayHelloActor 项目

四、代码实现


一、Actor 模型工作机制说明(复习)

1.Actor 间传递消息机制(对照工作机制示意图理解)

1)每一个消息就是一个 Message 对象。Message  继承了 Runable ,因为 Message 就是线程类。

2)从 Actor 模型工作机制看上去很麻烦,但是程序员编程时只需要编写 Actor 就可以了,其它的交给 Actor 模型完成即可。

3) A Actor 要给 B Actor 发送消息,那么 A Acto r 要先拿到(也称为持有)  B Actor的代理对象 ActorRef 才能发送消息


二、应用实例需求

1.编写一个 Actor,比如 SayHelloActor

2.SayHelloActor 可以给自己发送消息,如图

image.png

3.要求使用 Maven 的方式来构建项目,这样可以很好的解决项目开发包的依赖关系。

在进行 AKKA 开发时,要下载 AKKA 的开发包,自己下载比较麻烦,而且 Scala 的版本和 AKKA 有对应关系,如果 Scala 的版本和 AKKA 对应不上,则无法做开发,此时用 Maven 是最好的方式。

Actor 自我通讯机制原理图

1.初步理斛 Actor 通计机制

image.png

对上图的理解:

A Actor, A 有一个 ActorRef,通过 A Actor 发一个消息到 A Actor 的MailBox ,相当于A Actor 拿到消息,A ActorRef 引用,发消息到 Dispatcher Message,然后 Dispatcher Message 再将消息转发给 A Actor 里面的MailBox。MailBox 会将消息推送给 A Actor 里面的 receive 方法,并且给自己 A ActorRef 发送消息也会启动 Actor 的运行


三、SayHelloActor 项目

1.创建项 new->new Project ->选择Maven

2.给项目命名

image.png

3.下一步->finish

4.会生成 pom.xml 文件( maven文件,项目包的依赖)

image.png

5.将下面的 maven 配置模板拷贝到 pom.xml 文件中

<!--定义一常量-->

<properties>

<encoding>UTF-8</encoding>

<scala.version>2.11.8</scala.version>

<scala.compat.version>2.11</scala.compat.version>

<akka.version>2.4.17</akka.version>

</properties>

<dependencies>

<!--添加scala的依赖--->

<dependency>

<groupld>org.scala-lang</groupld>

<artifactld>scala-library</artifactld>

<version>$[scala.version}/version>

</dependency>

<!--添加akka 的 actor依赖-->

<dependency>

<groupld>com.typesafe.akka</groupld>

<artifactld>akka-actor_${scala.compat.version}</artifactld>

<version>${akka.version}</version>

</dependency>

<!--多进程之间的Actor通信-->

<dependency>

<groupld>com.typesafe.akka</groupld>

<artifactld>akka-remote_${scala.compat.version}</artifactld>

<version>${akka.version}/version>

</dependency>

</dependencies>

<!--指定插件-->

<build>

<!-指定源码包和测试包的位置-->

<sourceDirectory>src/main/scala</sourceDirectory>  

/*这里 scala 会有错误提示,因为目前没有在 main 中建一个 scala,此时要打开源码包,找到 main 新建一个目录叫 scala,然后在 scala 中找到 Mark Directory as 标记成 Sources Root ,继续再在 text 中新建一个 scala ,然后也将其标记为 Sources Root。此时会有提示,

如图:

image.png

点击引入改包,第一次下载速度较慢,需要10分钟到20分钟不等

*/

<testSourceDirectory>src/test/scala</testSourceDirectory>  //这里 scala 会有错误提示

<plugins>

<!--指定编译scala的插件-->

<plugin>

<groupld>net.alchim31.maven</groupld>

<artifactld>scala-maven-plugin</artifactld>

<version>3.2.2</version>

<executions>

<execution>

goals>

<goal>compile</goal>

<goal>testCompile</goal>

</goals>

<configuration>

<args>

<arg>-dependencyfile</arg>

<arg>${project.build.directory}/.scala_dependencies</arg>

</ args>

< / configuration>

< / execution>

</ executions>

</ plugin>

<!-- maven打包的插件-->

<plugin>

<groupld>org.apache.maven.plugins</groupld>

<artifactlas-maven-shade-plugin</artifactld>

<version>2.4.3</version>

<executions>

<execution>

<phase>package</phase>

<goals>

<goal>shade</goal>

</goals>

<configuration>

<filters>

<filter>

<artifact>*:*</artifact><excludes>

exclude>META-INF/*.SF</exclude>

<exclude>META-INF/*.DSA</exclude>

<exclude>META-INF/*.RSA</exclude>

</excludes>

</filter>

</filters>

<transformers>

<transformerimplementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">

resource>reference.conf</resource>

</transformer>

--指定main方法-→>

<transformerimplementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">

<mainClas s>xxx</ mainClass>

</transformer>

</transformers>

</configuration>

</execution>

</executions>

</plugin>

</plugins>

</build>

6.因为按照配置模板的内容"指定源码包和测试包的位置”的部分<sourceDirectory>src/main/scala</sourceDirectory>

<testSourceDirectory>src/test/scala</testSourceDirectory>

我们需要创建对应的 scala 目录,并 mark 为 sources root

7.当修改后,第一次速度比较慢,因为 maven 需要 resolve 包的依赖,要下载相关的包

注意:

如果下载相关包时无响应,需要如图勾选,update snapshots,而且不需要联网,如果使用 maven 解决依赖后,仍然 pom.xml 有误,则只需要重启下 idea,或者动一下 pom.xml 文件(不用改),重新保存即可.

image.png

上述准备完成后,可以做 scala 基本开发(如果想再加一个 scala 框架,发现无该选项,因为 maven 中已经将 scala 包引入了)


四、代码实现

import akka.actor . {Actor,Actorsystem}

//说明

//1.当我们继承 Actor 后,就是一个Actor ,核心方法 receive 方法重写

class sayHelloActor extends Actor{

/*说明

1. receive 方法,会被该 Actor 的MaiLBox (实现了Runnable接口)调用

2.当该 Actor MaiLBox 接收到消,息,就会调用receive(每个 Actor 都有一个邮箱)

3. type Receive = PartiaLFunction[ Any, unit] Receive 返回偏函数

*/

override def receive :Receive = {

case "hel1o" =>printLn("收到hello,回应hello too")

case "ok" =>println("收到ok,回应ok too")

case _=println("匹配不到")

}

}

object sayHelloActorDemo {  

//1.先创建—个 Actorsystem ,专门用于创建 Actor

private val actocyFactory = Actorsystem( "actoryFactory")

//2.创建一个 Actor 的同时,返回 Actor 的 ActorRef

/*

说明

(1)Props[SayHelloActor ] 创建了一个 sayHelloActor 实例,底层使用反射机制

(2)“sayHelloActor” 给 actor取名(注意名字不要重复)

(3)sayHelloActorRef:ActorRef 就是 Props[SayHelloActor ] ActorRef

(4)创建的 sayHelloActorRef:ActorRef 的实例,被 Actorsystem 接管

*/

private val sayHelloActorRef:ActorRef=actoryFactory.actorof

(Props[SayHelloActor ] , " sayHelloActor")

def main (arg:Array[String]):Unit)={

//sayHelloActor 发消息(邮箱)

sayHelloActorRef”hello”  //这里写的是谁就发给谁

}

}

运行结果为:

收到 hello,回应 hello too

注意:

在创建 sayHelloActorRef:ActorRef 对象时,[SayHelloActor ] 已经被创建,只是被 Actorsystem 接管了

sayHelloActorRef 不是一个真正的实例,只是跟[SayHelloActor ] 关联了,没有创建一个新的对象,下图以便理解:

image.png

在底层有一个SayHelloActor 实例,同时它将 sayHelloActorRef 引用,这个引用不理解为一个全新的东西,它只是为了和 SayHelloActor 关联。

然后发出消息这个动作,先把消息发给

Dispatcher Message 消息分发器,消息分发器会将消息打包,将消息序列化,然后将消息发给 sayHelloActor 底层对应的邮箱,MailBox Runable 的,可以一直处于运行状态。

MailBox 接收消息后,要将消息推送给 SayHelloActor 实例,因为在 MailBox 中是有SayHelloActor 的实例,该实例中有一个 receiver 方法,接收到消息后会调用 receiver 方法。

调用该方法可以理解为将消息推送给 SayHelloActor 实例中的方法。

部分代码:

def main (arg:Array[String]):Unit)={

sayHelloActorRef”hello”

}

将该部分代码改为

def main (arg:Array[String]):Unit)={

sayHelloActorRef”hello”

sayHelloActorRefok

}

运行结果为

收到 hello,回应 hello too

收到 ok,回应 ok too

(输出是有序的)

如果输出一个“ok~“,则会输出”匹配不到“

运行发现,程序并没有退出,因为底层的 MailBox Runable,没有手动停止则程序会一直运行,如果想要终止或退出,将下面代码改写:

override def receive :Receive = {

case "hel1o" =>printLn("收到hello,回应hello too")

case "ok" =>println("收到ok,回应ok too")

case _=println("匹配不到")

}

改写为:

override def receive :Receive = {

case "hel1o" =>printLn("收到hello,回应hello too")

case "ok" =>println("收到ok,回应ok too")

case “exit”=>{

println(“接收到 exit 指令,退出系统”)

context.stop(self)   //停止 actoref

context.system.terminate()  //退出 actory

case _=println("匹配不到")

}

执行该指令

def main (arg:Array[String]):Unit)={

sayHelloActorRefexit

}

相关文章
|
11月前
|
机器学习/深度学习 PyTorch TensorFlow
Pytorch介绍以及基本使用、深入了解、案例分析。(上)
Pytorch介绍以及基本使用、深入了解、案例分析。(上)
|
11月前
|
机器学习/深度学习 数据采集 存储
Pytorch介绍以及基本使用、深入了解、案例分析。(下)
Pytorch介绍以及基本使用、深入了解、案例分析。(下)
|
机器学习/深度学习 分布式计算 关系型数据库
直播预告 | pg4ml 机器学习框架系列课程:实现细节、XOR 模型案例(上)
pg4ml 机器学习框架是基于 PostgreSQL v13 实现的、使用 plpgsql 编写的机器学习框架,本次讲解的实验环境基于PolarDB-PG开源数据库。本次分享主要介绍框架的实现细节,并构建XOR两层网络的模型案例,包括数据集、XOR分类的案例与原理、神经网络节点、训练任务结构与执行等内容。
直播预告 |  pg4ml 机器学习框架系列课程:实现细节、XOR 模型案例(上)
|
缓存 算法 NoSQL
来吧,自己动手撸一个分布式ID生成器组件(上)
来吧,自己动手撸一个分布式ID生成器组件(上)
来吧,自己动手撸一个分布式ID生成器组件(上)
|
机器学习/深度学习 数据采集 算法
机器学习中令你事半功倍的pipeline处理机制​
机器学习中令你事半功倍的pipeline处理机制​
机器学习中令你事半功倍的pipeline处理机制​
|
机器学习/深度学习 SQL 数据采集
阿里云机器学习平台PAI基本操作演示|学习笔记
快速学习阿里云机器学习平台PAI基本操作演示
656 0
阿里云机器学习平台PAI基本操作演示|学习笔记
|
机器学习/深度学习 存储 Kubernetes
推荐系统基本概念及架构说明|学习笔记
快速学习推荐系统基本概念及架构说明
272 0
推荐系统基本概念及架构说明|学习笔记
|
运维 负载均衡 关系型数据库
来吧,自己动手撸一个分布式ID生成器组件(下)
来吧,自己动手撸一个分布式ID生成器组件(下)
来吧,自己动手撸一个分布式ID生成器组件(下)
|
机器学习/深度学习
ML之Validation:机器学习中模型验证方法的简介、代码实现、案例应用之详细攻略
ML之Validation:机器学习中模型验证方法的简介、代码实现、案例应用之详细攻略
ML之Validation:机器学习中模型验证方法的简介、代码实现、案例应用之详细攻略
|
TensorFlow 算法框架/工具
TF学习——Tensorflow框架之基础概念、设计思路、常用方法之详细攻略
TF学习——Tensorflow框架之基础概念、设计思路、常用方法之详细攻略