Akka Actor入门示例

来源:互联网 发布:生活大爆炸知乎 编辑:程序博客网 时间:2024/06/05 20:32
什么是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"))
            }
        }
    }
}