硕大的汤姆

硕大的汤姆

The official website of Minhua Chen

01 Apr 2018

akka

akka 不是一个 framework,而是一个 toolkit 或者说运行时,用于在 jvm 上构建高并发、分布式、弹性、消息驱动的应用。Actor 执行操作来响应消息。这些操作包括更改 actor 自己的内部状态,以及发出其他消息和创建其他 actor。所有消息都是异步交付的,因此将消息发送方与接收方分开。这种分离,使得 actor 系统具有内在的并发性:可以不受限制地并行执行任何拥有输入消息的 actor。

像真实世界的演员一样,Akka actor 也需要一定程度的隐私。您不能直接将消息发送给 Akka actor。相反,需要将消息发送给等同于邮政信箱的 actor 引用。然后通过该引用将传入的消息路由到 actor 的邮箱,以后再传送给 actor。Akka actor 甚至要求所有传入的消息都是不可变的。

与一些真实世界中演员的需求不同,Akka 中由于某种原因而存在一些看似强制要求的限制。 使用 actor 的引用可阻止交换消息以外的任何交互,这些交互可能破坏 actor 模型核心上的解耦本质。 Actor 在执行上是单线程的(不超过 1 个线程执行一个特定的 actor 实例),所以邮箱充当着一个缓冲器,在处理消息前会一直保存这些消息。 消息的不可变性意味着根本无需担心可能影响 actor 之间各种共享的数据的同步问题。

actors

sending messages changing its state changing its behavior creating more actors

class Activity

class Disable(val password: String)

class Enable(val password: String)

class Alarm(val password: String): AbstractLoggingActor() {
    override fun createReceive(): Receive {
        return disabled
    }

    val enabled = receiveBuilder()
            .match(Activity::class.java, { this.onActivity(it) })
            .match(Disable::class.java, { this.onDisable(it) })
            .build()

    val disabled = receiveBuilder()
            .match(Enable::class.java, { this.onEnable(it) }).build()

    private fun onDisable(disable: Disable) {
        if (password == disable.password) {
            log().info("alarm disabled")
            context.become(disabled)
        } else {
            log().warning("wrong password")
        }
    }

    private fun onEnable(enable: Enable) {
        if (password == enable.password) {
            log().info("alarm enabled")
            context.become(enabled)
        } else {
            log().warning("failed to enable the alarm")
        }
    }

    private fun onActivity(a: Activity) {
        log().warning("alarm")
    }

    companion object {
        fun props(password: String) = Props.create(Alarm::class.java, password)
    }
}

fun main(args: Array<String>) {
    val system = ActorSystem.create()

    val alarm = system.actorOf(Alarm.props("pass"), "alarm")

    alarm.tell(Activity(), ActorRef.noSender())
    alarm.tell(Enable("puss"), ActorRef.noSender())
    alarm.tell(Enable("pass"), ActorRef.noSender())
    alarm.tell(Activity(), ActorRef.noSender())
    alarm.tell(Disable("puss"), ActorRef.noSender())
    alarm.tell(Disable("pass"), ActorRef.noSender())
}