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不应该堵塞自己运行的线程