代码语言:javascript复制
package actor
import akka.actor.{Actor, ActorSystem, Props}
/**
* 当继承actor后,就是一个Actor,核心方法receive 方法重写
*/
class SayHelloActor extends Actor {
/**
* 1. receive 方法,会被Actor的mailbox(实现了Runnable接口)调用
* 2.当该Actor的mailbox 接收到消息,就会调用了receive
* 3.type receive = PartialFunction[Any,Unit]
*
* @return
*/
override def receive: Receive = {
case "hello" => println("收到hello,回应hello too :)")
case "ok" => println("收到ok,回应ok too :)")
case "exit" => {
println("接收到exit,退出系统")
context.stop(self) //停止actorref
context.system.terminate() // 退出actorsystem
}
case _ => println("匹配不到")
}
}
object SayHelloActor {
//1.先创建一个ActorSystem,专门用于创建Actor
val actorFactory = ActorSystem("actorFactory")
//2.创建一个Actor的同时,返回Actor的ActorRef
//Props[SayHelloActor] c创建了一个sayhelloActor实例,使用反射
//“sayhelloactor" 给actor取名
//sayHelloActorRef :Actor就是Props[SayHelloActor] 的ActorRef
//创建的sayhelloRef 被ActorSystem接管
val sayHelloActorRef = actorFactory.actorOf(Props[SayHelloActor], "sayHelloActor")
def main(args: Array[String]): Unit = {
//给SayHelloActor 发消息(邮箱)
sayHelloActorRef ! "hello"
sayHelloActorRef ! "ok"
sayHelloActorRef ! "exit"
}
}
简单来说,Actor通过消息传递的方式与外界通信,而且消息传递是异步的。每个Actor都有一个邮箱,邮箱接收并缓存其他Actor发过来的消息,通过邮箱队列mail queue
来处理消息。Actor一次只能同步处理一个消息,处理消息过程中,除了可以接收消息外不能做任何其他操作。
每个Actor是完全独立的,可以同时执行他们的操作。每个Actor是一个计算实体,映射接收到的消息并执行以下动作:发送有限个消息给其他Actor、创建有限个新的Actor、为下一个接收的消息指定行为。这三个动作没有固定的顺序,可以并发地执行,Actor会根据接收到的消息进行不同的处理。
在Actor系统中包含一个未处理的任务集,每个任务都由三个属性标识:
tag
用以区分系统中的其他任务target
通信到达的地址communication
包含在target
目标地址上的Actor,处理任务时可获取的信息。
为简单起见,可见一个任务视为一个消息,在Actor之间传递包含以上三个属性的值的消息。
Actor模型有两种任务调度方式:基于线程的调度、基于事件的调度
- 基于线程的调度 为每个Actor分配一个线程,在接收一个消息时,如果当前Actor的邮箱为空则会阻塞当前线程。基于线程的调度实现较为简单,但线程数量受到操作的限制,现在的Actor模型一般不采用这种方式。
- 基于事件的调度 事件可以理解为任务或消息的到来,而此时才会为Actor的任务分配线程并执行。
因此,可以把系统中所有事物都抽象成为一个Actor:
- Actor的输入是接收到的消息
- Actor接收到消息后处理消息中定义的任务
- Actor处理完成任务后可以发送消息给其它Actor
在一个系统中可以将一个大规模的任务分解为一些小任务,这些小任务可以由多个Actor并发处理,从而减少任务的完成时间。
Actor
模型本身确保处理是按照同步的方式执行的。TicketsActor
会处理其收件箱中的每条消息,注意这里没有复杂的线程或锁,只是一个多线程的处理过程,但Actor
系统会管理线程的使用和分配。
Actor是由状态(state)、行为(behavior)、邮箱(mailbox)三者组成的。
- 状态(state):状态是指actor对象的变量信息,状态由actor自身管理,避免并发环境下的锁和内存原子性等问题。
- 行为(behavior):行为指定的是actor中计算逻辑,通过actor接收到的消息来改变actor的状态。
- 邮箱(mailbox):邮箱是actor之间的通信桥梁,邮箱内部通过FIFO消息队列来存储发送发消息,而接收方则从邮箱中获取消息。
Actor模型描述了一组为避免并发编程的公理:
- 所有的Actor状态是本地的,外部是无法访问的。
- Actor必须通过消息传递进行通信
- 一个Actor可以响应消息、退出新Actor、改变内部状态、将消息发送到一个或多个Actor。
- Actor可能会堵塞自己但Actor不应该堵塞自己运行的线程