什么是Akka?
Akka通常是指一个分布式工具集,用于协调远程计算资源来进行一些工作,是Actor并发模型的一种实现。


Actor的起源?
一篇论文提出了一种并发计算的理论模型。


什么是Actor?
在Actor模型中,Actor是一个并发原语。


Actor和消息传递
如果多线程同时读取并修改同一值,那么可能就需要进行同步并加锁。
Actor和对象的不同之处在于其不能被直接读取、修改或是调用。Actor只能通过消息传递的方式与外界进行通信。
消息传递指的是一个Actor可以接收消息,本身也可以发送消息,也可以对接受到的消息作出回复。
消息传递是异步的。无论是处理消息还是回复消息,Actor对外界都没有依赖。
Actor每次只同步处理一个消息。邮箱的本质是等待Actor处理的一个工作队列。


几个重要的概念
Actor:一个表示工作节点的并发原语,同步处理接收到的消息。Actor可以保存并修改内部状态。
消息:用于跨进程(比如多个Actor之间)通信的数据。
消息传递:一种软件开发范式,通过传递消息来触发各种行为,而不是直接触发行为。
邮箱地址:消息传递的目标地址,当Actor空闲时会从该地址获取消息进行处理。
Actor系统:多个Actor的集合以及这些Actor的邮箱地址、邮箱和配置等。


Actor的好处:
1.每个Actor各司其职。
2.消除共享状态。
在多线程编程中,为了保证内存中的共享状态值不出现错误,使用锁和同步机制,防止多个线程读取并写入同一个值。
Actor通过减少共享状态来解决这一问题。


创建第一个Actor
1.首先构造消息
通过case class来创建不可变消息,一旦在构造函数中设置属性初始值,之后就只能够读取属性值,不能再进行修改。
case class SetRequest(key: String, value: Object)


2.定义Actor收到消息后的响应
既然已经定义好了消息,现在我们就可以创建Actor,并描述Actor接收到消息如何做出反应。

import akka.actor.Actor
 import akka.event.Logging
 import scala.collection.mutable.HashMap


 class AkkademyDb  extends Actor {
     val map = new HashMap[String, Object]
     val log = Logging(context.system, this)


     override def receive = {
         case SetRequest(key, value) => {
             log.info("received SetRequest - key: {} value: ", key , value)
             map.put(key, value)
         }
         case o => log.info("received unknown message: {}", o)
     }
 }


 3.与Actor进行交互
 import akka.actor.ActorSystem
 import akka.testkit.TestActorRef
 import akka.util.Timeout
 import org.scalatest.{FunSpecLike, Matchers}
 import scala.concurrent.duration._


 class AkkademyDbSpec extends FunSpecLike with Matchers {
     implicits val system = ActorSystem()//获取Actor系统
     implicits val timeout = Timeout(5 seconds)


     describe("akkademyDb") {
         describe("given SetRequest") {
             it("should place key/value into map") {
                 val actorRef = TestActorRef(new AkkademyDb)//在Actor系统中创建Actor
                 actorRef ! SetRequest("key", "value")
                 //!传递消息将消息放入Actor的邮箱中


                 //指向背后Actor实例的引用
                 val akkademyDb = actorRef.underlyingActor
                 //调用get("key")检查map,确认已经将值存入map中
                 akkademyDb.map.get("key") should equal (Some("value"))
             }
         }
     }
 }