2018-11-23 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。

可通过以下代码来初始化ActorSystem

val 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队列来存储消息,有一点不同的是,现实中我们的最新邮件

会在邮箱的最前面。

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消息

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容

  • Actor系统的实体 在Actor系统中,actor之间具有树形的监管结构,并且actor可以跨多个网络节点进行透...
    JasonDing阅读 3,326评论 2 6
  • 持久化 当我们在集群系统中,一台机器向另一台机器发送一段数据,负责接收的机器在接收数据前突然宕机,就会造成数据丢失...
    mango_knight阅读 4,495评论 0 4
  • 北京时间2019年4月20日,Erlang之父Joe Armstrong去世,享年68岁,致敬真正的思想者(还有...
    Queen〇fLaponia阅读 1,363评论 3 3
  • 一 什么是Actor模型? 这里直接引用官网的图片: 这里面描述了一个Actor包含了: Mailbox(邮箱):...
    Notput阅读 1,742评论 0 3
  • 冬日赶集 作者:高英 天冷收白菜, 萝卜街头卖。 白菜显胖瘦, 萝卜分青白。 胖瘦有人买, 青白有人爱。 所需各自...
    泠风思语阅读 195评论 0 4