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消息
参考文章:
https://rerun.me/tag/akka/page/2/
Actor模型及原理的更多相关文章
- 以Akka为示例,介绍Actor模型
许多开发者在创建和维护多线程应用程序时经历过各种各样的问题,他们希望能在一个更高层次的抽象上进行工作,以避免直接和线程与锁打交道.为了帮助这些开发者,Arun Manivannan编写了一系列的博客帖 ...
- Actor模型原理
1.Actor模型 在使用Java进行并发编程时需要特别的关注锁和内存原子性等一系列线程问题,而Actor模型内部的状态由它自己维护即它内部数据只能由它自己修改(通过消息传递来进行状态修改),所以使用 ...
- 10 分钟了解 Actor 模型
http://www.moye.me/2016/08/14/akka-in-action_actor-model/ 过去十几年CPU一直遵循着摩尔定律发展,单核频率越来越快,但是最近这几年,摩尔定律已 ...
- .NET的Actor模型:Orleans
Orleans是微软推出的类似Scala Akka的Actor模型,Orleans是一个建立在.NET之上的,设计的目标是为了方便程序员开发需要大规模扩展的云服务, 可用于实现DDD+EventSou ...
- 大数据运算模型 MapReduce 原理
大数据运算模型 MapReduce 原理 2016-01-24 杜亦舒 MapReduce 是一个大数据集合的并行运算模型,由google提出,现在流行的hadoop中也使用了MapReduce作为计 ...
- 根据老赵轻量级Actor进行修改的Actor模型
学习了老赵轻量级Actor模型,并在实际中使用,效果不错. 老赵轻量级Actor模型: ActorLite:一个轻量级Actor模型实现(上) ActorLite:一个轻量级Actor模型实现(中) ...
- Orleans:NET的Actor模型
.NET的Actor模型:Orleans Orleans是微软推出的类似Scala Akka的Actor模型,Orleans是一个建立在.NET之上的,设计的目标是为了方便程序员开发需要大规模扩展 ...
- Actor模型[转]
原文链接:http://blog.jeoygin.org/archives/477 Actor这个模型由Carl Hewitt在1973年提出,Gul Agha在1986年发表技术报告“Actors: ...
- 终结python协程----从yield到actor模型的实现
把应用程序的代码分为多个代码块,正常情况代码自上而下顺序执行.如果代码块A运行过程中,能够切换执行代码块B,又能够从代码块B再切换回去继续执行代码块A,这就实现了协程 我们知道线程的调度(线程上下文切 ...
随机推荐
- Django 1.11 release note简明解读
1.首先1.11这个版本是一个LTS版本 2.第一个支持python3.6的版本,最后一个支持python2.*的版本 3.Deprecating warnings 默认不再显示,同时建议第三方包开始 ...
- jQuery匿名函数$(function(){ }
搬运原地址:https://zhidao.baidu.com/question/473318430.html $(function(){ }实际上是匿名函数.这是JQuery的语法,$表示JQuery ...
- 大型三甲医院信息管理系统源码 His系统功能齐全 完整可用
详情请点击查看 开发环境 :Asp.net + VS2005 + C# + SQL2010(含三种数据库access,oracle,sql server) 采用了BS+ActiveX + Web ...
- sudo apt-get 与 yum安装有啥区别
rpm包和deb包是两种Linux系统下最常见的安装包格式,在安装一些软件或服务的时候免不了要和它们打交道. rpm包主要应用在RedHat系列包括 Fedora等发行版的Linux系统上, deb包 ...
- 使用webpack打包vue工程
记得去年十月份的时候,自己在研究webpack,当时只是知道大致的用法,写了一个简单的demo,现在,经过了7个月对公司产品架构的使用,以及对vue-cli的使用,在了解了实际应用中各种需求之后,我自 ...
- 有终将被编程潮流淹没的程序员,那是因为没学python人工智能吧?
2017年被称为中国人工智能元年--在两会时期,人工智能曾经成为国度计策,同时被写进当局报告.在从前的一年里,人工智能获得注重,已逐步浸透到别的行业,无人超市.主动驾驶.人脸识别.智能家居等" ...
- Java多线程:生命周期,实现与调度
Java线程生命周期 Java线程实现方法 继承Thread类,重写run()方法 实现Runnable接口,便于继承其他类 Callable类替换Runnable类,实现返回值 Future接口对任 ...
- va_start,va_arg,va_end的使用
一.在C中,当我们无法列出传递函数的所有实参的类型和数目时,可以用省略号指定参数表. void fun(...); void fun(parm_list,...); #include <stdi ...
- Git分支合并冲突解决
前2天群里发了张git历史图,如下: 根据提交历史,可以看出图中所有分支合并都采用merge的方式,具体merge是怎么操作的,可以阅读下边文章. 根据项目上的需求,如果要求git提交历史是比较简单的 ...
- linux内核堆栈
一:进程的堆栈 内核在创建进程的时候,在创建task_struct的同时会为进程创建相应的堆栈.每个进程会有两个栈,一个用户栈,存在于用户空间,一个内核栈,存 在于内核空间.当进程在用户空间运行时,c ...