Scala AKKA模型工作机制

纸上得来终觉浅,绝知此事要躬行!

Akka 介绍

1)Akka是JAVA虚拟机JVM平台上构建高并发、分布式和容错应用的工具包和运行时,你可以理解成Akka是编写并发程序的框架。

2)Akka用Scala语言写成,同时提供了Scala和JAVA的开发接口。

3)Akka主要解决的问题是:可以轻松的写出高效稳定的并发程序,程序员不再过多的考虑线程、锁和资源竞争等细节。

Akka 中 Actor(角色) 模型

Actor 模型用于解决什么问题

1)处理并发问题关键是要保证共享数据的一致性和正确性,因为程序是多线程时,多个线程对同一个数据进行修改,若不加同步条件,势必会造成数据污染。但是当我们对关键代码加入同步条件synchronized 后,实际上大并发就会阻塞在这段代码,对程序效率有很大影响。

2)若是用单线程处理,不会有数据一致性的问题,但是系统的性能又不能保证。

3)Actor 模型的出现解决了这个问题,简化并发编程,提升程序性能。 你可以这里理解:Actor 模型是一种处理并发问题的解决方案,很牛!

Actor模型及其说明

1)Akka 处理并发的方法基于 Actor 模型。(示意图)

2)在基于 Actor 的系统里,所有的事物都是 Actor,就好像在面向对象设计里面所有的事物都是对象一样。

3)Actor 模型是作为一个并发模型设计和架构的。Actor 与 Actor 之间只能通过消息通信(而且要求通过ActorRef来发消息),如图的信封.

4)Actor 与 Actor 之间只能用消息进行通信,当一个 Actor 给另外一个 Actor发消息,消息是有顺序的(消息队列),只需要将消息投寄的相应的邮箱即可。

5)怎么处理消息是由接收消息的Actor决定的,发送消息Actor可以等待回复,也可以异步处理

6)ActorSystem 的职责是负责创建并管理其创建的 Actor, ActorSystem 是单例的(可以ActorSystem是一个工厂,专门创建Actor),一个 JVM 进程中有一个即可,而 Acotr 是可以有多个的。

7)Actor模型是对并发模型进行了更高的抽象。

8)Actor模型是异步、非阻塞、高性能的事件驱动编程模型。

9)Actor模型是轻量级事件处理(1GB 内存可容纳百万级别个 Actor),因此处理大并发性能高.

Actor模型工作机制说明

1)A Actor 如果想给自己发消息,就通过A ActorRef

2)A Actor 想给B Actor 发消息,就需要有(持有)B  ActorRef , 通过B ActorRef 发消息

3)发送消息总是通过ActorRef 完成

B Actor 中

receive 方法 { //1.消息接收和处理

//2. 通过sender() 方法可以得到发送消息的Actor的ActorRef, 通过这个ActorRef  ,B Actor 也可以回复消息给A Actor

}

Actor模型工作机制说明

1)ActorySystem创建Actor

2)ActorRef:可以理解成是Actor的代理或者引用。消息是通过ActorRef来发送,而不能通过Actor 发送消息,通过哪个ActorRef 发消息,就表示把该消息发给哪个Actor

3)消息发送到Dispatcher Message (消息分发器),它得到消息后,会将消息进行分发到对应的MailBox。(注: Dispatcher Message 可以理解成是一个线程池, MailBox 可以理解成是消息队列,可以缓冲多个消息,遵守FIFO)

4)Actor 可以通过 receive方法来获取消息,然后进行处理。

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

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

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

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

lActor模型快速入门

Actor自我通讯机制原理图

class SayHelloActorDemo extends Actor {
override def receive: Receive = {
// 接受消息并处理,如果接收到exit,就退出
case “hello” => println(“发送:hello\t\t回应: hello too:)”)
case “ok” => println(“发送:ok\t\t\t回应: ok too:)”)
case “exit” => {
println(“接收到exit~指令,退出系统…”)
context.stop(self) // 停止自己的actorRef
context.system.terminate() // 关闭ActorSystem
}
}
}

object SayHelloActor {
private val actoryFactory = ActorSystem(“ActoryFactory”)
private val sayHelloActorRef: ActorRef = actoryFactory.actorOf( Props[SayHelloActor],“sayHelloActor”)

def main(args: Array[String]): Unit = {
// 给sayHelloActorRef发送消息
// !是方法名,可以看下源码
sayHelloActorRef ! “hello”
sayHelloActorRef ! “ok”

//如果不发送exit, Actor就会等待接收消息,而不会退出程序.
sayHelloActorRef ! "exit"

}

}

小结和说明

当程序执行 aActorRef = actorFactory.actorOf(Props[AActor], “aActor”) ,会完成如下任务 [这是非常重要的方法]

1)actorFactory 是 ActorSystem(“ActorFactory”) 这样创建的。

2)这里的 Props[AActor] 会使用反射机制,创建一个AActor 对象,如果是actorFactory.actorOf(Props(new AActor(bActorRef)), “aActorRef”) 形式,就是使用new 的方式创建一个AActor对象, 注意Props() 是小括号。

3)会创建一个AActor 对象的代理对象 aActorRef , 使用aActorRef 才能发送消息

4)会在底层创建 Dispather Message ,是一个线程池,用于分发消息, 消息是发送到对应的Actor的 MailBox

5)会在底层创建AActor 的MailBox 对象,该对象是一个队列,可接收Dispatcher Message 发送的消息

6)MailBox 实现了Runnable 接口,是一个线程,一直运行并调用Actor的receive 方法,因此当Dispather 发送消息到MailBox时,Actor 在receive 方法就可以得到信息.

7)aActorRef !  “hello”, 表示把hello消息发送到A Actor 的mailbox (通过Dispatcher Message 转发)

Actor模型应用实例-Actor间通讯

class AActor(bActorRef: ActorRef) extends Actor {
override def receive: Receive = {
case “start” => {
println(“AActor(黄飞鸿) 开始游戏了”)
bActorRef ! “我打”}
case “我打” => {
println(s"AActor(黄飞鸿) 厉害 看我佛山无影脚~~~~ 第$attact 脚" )
Thread.sleep(1000)
bActorRef ! “我打”
}}}

class BActor extends Actor { //BActor.scala
override def receive: Receive = {
case “我打” => {
println(s"BActor(乔峰): 挺猛的 看我降龙十八掌~ 第$attack 掌")
Thread.sleep(1000)
sender() ! “我打”
}}}

object ActorsGame { //ActorsGame.scala
def main(args: Array[String]): Unit = {
val actorFactory = ActorSystem(“actorFactory”)
val bActorRef = actorFactory.actorOf(Props[BActor],“bActor”)
val aActorRef = actorFactory.actorOf(Props(new AActor(bActorRef)),“aActor”)
aActorRef ! “start”
}
}

小结和说明

1)两个Actor通讯机制和Actor 自身发消息机制基本一样,只是要注意如下

2)如果A Actor 在需要给B Actor 发消息,则需要持有B Actor 的 ActorRef,可以通过创建时,传入 B Actor的 代理对象(ActorRef)

3)当B Actor 在receive 方法中接收到消息,需要回复时,可以通过sender() 获取到发送Actor的 代理对象。

Ø如何理解Actor 的receive 方法被调用?

1)每个Actor对应MailBox

2)MailBox 实现了Runnable 接口,处于运行的状态

3)当有消息到达MailBox,就会去调用Actor的receive方法,将消息推送给receive

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

研程序笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值