Actor模型原理
1.Actor模型
在使用Java进行并发编程时需要特别的关注锁和内存原子性等一系列线程问题,而Actor模型内部的状态由它自己维护即它内部数据只能由它自己修改(通过消息传递来进行状态修改),所以使用Actors模型进行并发编程可以很好地避免这些问题,Actor由状态(state)、行为(Behavior)和邮箱(mailBox)三部分组成
- 状态(state):Actor中的状态指的是Actor对象的变量信息,状态由Actor自己管理,避免了并发环境下的锁和内存原子性等问题
- 行为(Behavior):行为指定的是Actor中计算逻辑,通过Actor接收到消息来改变Actor的状态
- 邮箱(mailBox):邮箱是Actor和Actor之间的通信桥梁,邮箱内部通过FIFO消息队列来存储发送方Actor消息,接受方Actor从邮箱队列中获取消息
Actor的基础就是消息传递
2.使用Actor模型的好处:
- 事件模型驱动--Actor之间的通信是异步的,即使Actor在发送消息后也无需阻塞或者等待就能够处理其他事情
- 强隔离性--Actor中的方法不能由外部直接调用,所有的一切都通过消息传递进行的,从而避免了Actor之间的数据共享,想要
观察到另一个Actor的状态变化只能通过消息传递进行询问 - 位置透明--无论Actor地址是在本地还是在远程机上对于代码来说都是一样的
- 轻量性--Actor是非常轻量的计算单机,单个Actor仅占400多字节,只需少量内存就能达到高并发
3.Actor模型原理
以下通过学生与教师之间的邮件通信来理解akka中的Actor模型
学生-教师的消息传递
首先先只考虑学生单向发送消息给教师(学生--->教师),如下图:
图解:
- 学生创建一个ActorSystem
- 通过ActorSystem创建ActorRef,将QuoteRequest消息发送到ActorRef(教师代理)
- ActorRef(教师代理)消息传递到Dispatcher中
- Dispatcher依次的将消息发送到TeacherActor的邮箱中
- Dispatcher将邮箱推送到一条线程中
- 邮箱取出一条消息并委派给TeacherActor的receive方法
下面再详细的解释每一步骤
StudentSimulatorApp主程序详解:
首先StudentSimulatorApp会先启动JVM并初始化ActorSystem
如上图所示,StudentSimulatorApp的主要工作为:
- 创建ActorSystem
ActorSystem作为顶级Actor,可以创建和停止Actors,甚至可关闭整个Actor环境,
此外Actors是按层次划分的,ActorSystem就好比Java中的Object对象,Scala中的Any,
是所有Actors的根,当你通过ActorSystem的actof方法创建Actor时,实际就是在ActorSystem
下创建了一个子Actor。
可通过以下代码来初始化ActorSystemval system = ActorSystem("UniversityMessageSystem")
- 通过ActorSystem创建TeacherActor的代理(ActorRef)
看看TeacherActor的代理的创建代码
val teacherActorRef:ActorRef = system.actorOf(Props[TeacherActor])
ActorSystem通过actorOf创建Actor,但其并不返回TeacherActor而是返
回一个类型为ActorRef的东西。
ActorRef作为Actor的代理,使得客户端并不直接与Actor对话,这种Actor
模型也是为了避免TeacherActor的自定义/私有方法或变量被直接访问,所
以你最好将消息发送给ActorRef,由它去传递给目标Actor - 发送QuoteRequest消息到代理中
你只需通过!方法将QuoteReques消息发送给ActorRef(注意:ActorRef也有个tell方法,其作用就委托回调给!)
techerActorRef!QuoteRequest
等价于teacherActorRef.tell(QuoteRequest, teacherActorRef)
完整StudentSimulatorApp代码
object StudentSimulatorApp extends App{
//初始化ActorSystem
val actorSystem=ActorSystem("UniversityMessageSystem")
//构建teacherActorRef
val teacherActorRef=actorSystem.actorOf(Props[TeacherActor])
//发送消息给TeacherActor
teacherActorRef! QuoteRequest
Thread.sleep (2000)
//关闭 ActorSystem,如果不关闭JVM将不会退出
actorSystem.shutdown()
}
QuoteRequest类
object TeacherProtocol{
case class QuoteRequest() //请求
case class QuoteResponse(quoteString:String) //响应
}
Dispatcher和MailBox
ActorRef将消息处理能力委派给Dispatcher,实际上,当我们创建ActorSystem和ActorRef时,
Dispatcher和MailBox就已经被创建了
MailBox
- 每个Actor都有一个MailBox,同样,Teacher也有个MailBox,其会检查MailBox并处理消息。
MailBox内部采用的是FIFO队列来存储消息,有一点不同的是,现实中我们的最新邮件
会在邮箱的最前面。
- 每个Actor都有一个MailBox,同样,Teacher也有个MailBox,其会检查MailBox并处理消息。
Dispatcher
Dispatcher从ActorRef中获取消息并传递给MailBox,Dispatcher封装了一个线程池,之后在
线程池中执行MailBox。protected[akka] override def registerForExecution(mbox: Mailbox, ...): Boolean = {
...
try {
executorService execute mbox
...
}- 为什么能执行MailBox?
看看MailBox的实现,没错,其实现了Runnable接口
private[akka] abstract class Mailbox(val messageQueue: MessageQueue) extends SystemMessageQueue with Runnable
TeacherActor
当ActorRef发送消息调用目标Actor的reveive方法时,MailBox中的run方法被执行,接着从消息队列中取出一条消息并传递给Actor处理
class TeacherActor extends Actor {
val quotes = List(
"Moderation is for cowards",
"Anything worth doing is worth overdoing",
"The trouble is you think you have time",
"You never gonna know if you never even try")
def receive = {
case QuoteRequest => {
import util.Random
//从list中随机选出一条消息作为回应(这里只print并没回应学生的请求)
val quoteResponse=QuoteResponse(quotes(Random.nextInt(quotes.size)))
println (quoteResponse)
}
}
}
TeacherActor的receive方法将匹配QuoteRequest消息
这里有个国外博主写的Akka系列博客都很赞,分享给大家!
本文参考资料:
AKKA NOTES - ACTOR MESSAGING - 1
Akka框架——第一节:并发编程简介
Akka Quickstart with Scala
Actor模型原理的更多相关文章
- Actor模型及原理
1.Actor模型 在使用Java进行并发编程时需要特别的关注锁和内存原子性等一系列线程问题,而Actor模型内部的状态由它自己维护即它内部数据只能由它自己修改(通过消息传递来进行状态修改),所以使用 ...
- 10 分钟了解 Actor 模型
http://www.moye.me/2016/08/14/akka-in-action_actor-model/ 过去十几年CPU一直遵循着摩尔定律发展,单核频率越来越快,但是最近这几年,摩尔定律已 ...
- 以Akka为示例,介绍Actor模型
许多开发者在创建和维护多线程应用程序时经历过各种各样的问题,他们希望能在一个更高层次的抽象上进行工作,以避免直接和线程与锁打交道.为了帮助这些开发者,Arun Manivannan编写了一系列的博客帖 ...
- .NET的Actor模型:Orleans
Orleans是微软推出的类似Scala Akka的Actor模型,Orleans是一个建立在.NET之上的,设计的目标是为了方便程序员开发需要大规模扩展的云服务, 可用于实现DDD+EventSou ...
- Actor的原理
先从著名的c10k问题谈起.有一个叫Dan Kegel的人在网上(http://www.kegel.com/c10k.html)提出:现在的硬件应该能够让一台机器支持10000个并发的client.然 ...
- word2vec模型原理与实现
word2vec是Google在2013年开源的一款将词表征为实数值向量的高效工具. gensim包提供了word2vec的python接口. word2vec采用了CBOW(Continuous B ...
- 【转】Select模型原理
Select模型原理利用select函数,判断套接字上是否存在数据,或者能否向一个套接字写入数据.目的是防止应用程序在套接字处于锁定模式时,调用recv(或send)从没有数据的套接字上接收数据,被迫 ...
- Select模型原理
Select模型原理 利用select函数,推断套接字上是否存在数据,或者是否能向一个套接字写入数据.目的是防止应用程序在套接字处于锁定模式时,调用recv(或send)从没有数据的套接字上接收数据, ...
- 根据老赵轻量级Actor进行修改的Actor模型
学习了老赵轻量级Actor模型,并在实际中使用,效果不错. 老赵轻量级Actor模型: ActorLite:一个轻量级Actor模型实现(上) ActorLite:一个轻量级Actor模型实现(中) ...
随机推荐
- 记一次 net 使用 data.oracleclient 使用错误
前提: 公司除了领导和开发人员具有管理员权限,其他人员使用的都是域账号. 过程: 应要求开发一个 winfrom项目,使用data.oracleclient 本地开发,调试无误,放到服务器共享域用户 ...
- ajax基础知识、用ajax做登录页面、用ajax验证用户名是否可用、ajax动态调用数据库
1.ajax的基础知识 ajax是结合了jquery.php等几种技术延伸出来的综合运用的技术,不是新的内容.ajax也是写在<script>标签里面的. 如果使用ajax一定是要有1个处 ...
- Linux find运行机制详解
本文目录: 1.1 find基本用法示例 1.2 find理论部分 1.2.1 expression-operators 1.2.2 expression-options 1.2.3 expressi ...
- RSA加密通信小结(三)--生成加解密所需的SSL命令与流程
在iOS中使用RSA加密解密,需要用到.der和.p12后缀格式的文件,其中.der格式的文件存放的是公钥(Public key)用于加密,.p12格式的文件存放的是私钥(Private key)用于 ...
- 实现最简单PHP MVC实例
关于网上大多MVC的简介我就不再多说,就是Model(模型)View(视图) C(控制器)这里作为一个刚入门PHP MVC框架的我,这里我搭建一个最简易的mvc项目,从而理解MVC 1在apache服 ...
- 高性能队列Disruptor系列3--Disruptor的简单使用(译)
简单用法 下面以一个简单的例子来看看Disruptor的用法:生产者发送一个long型的消息,消费者接收消息并打印出来. 首先,我们定义一个Event: public class LongEvent ...
- 【踩坑记录】记一次MySQL主从复制延迟的坑
最近开发中遇到的一个MySQL主从延迟的坑,记录并总结,避免再次犯同样的错误. 情景 一个活动信息需要审批,审批之后才能生效.因为之后活动要编辑,编辑后也可能触发审批,审批中展示的是编辑前的活动内容, ...
- Linux网络编程客户\服务器设计范式
1.前言 网络编程分为客户端和服务端,服务器通常分为迭代服务器和并发服务器.并发服务器可以根据多进程或多线程进行细分,给每个连接创建一个独立的进程或线程,或者预先分配好多个进程或线程等待连接的请求.今 ...
- Kafka官方文档翻译——实现
IMPLEMENTATION 1. API Design Producer APIs Producer API封装了底层两个Producer: kafka.producer.SyncProducer ...
- oracle学习笔记(2)-基本术语
oracle基本术语 先上图. 相当粗糙的一个图,可能有些地方不够精细,大致结构基本是对的. 逻辑结构上从大到小的依次为文件(file)->表空间(tablespace)->段(segme ...