本文由 GodPan 发表在 ScalaCool 团队博客。git
Akka是一个构建在JVM上,基于Actor模型的的并发框架,为构建伸缩性强,有弹性的响应式并发应用提升更好的平台。本文主要是我的对Akka的学习和应用中的一些理解。程序员
Akka的核心就是Actor,因此不得不说Actor,Actor模型我通俗的举个例子,假定现实中的两我的,他们只知道对方的地址,他们想要交流,给对方传递信息,可是又没有手机,电话,网络之类的其余途径,因此他们之间只能用信件传递消息,很像现实中的的邮政系统,你要寄一封信,只需根据地址把信投寄到相应的信箱中,具体它是如何帮你处理送达的,你就不须要了解了,你也有可能收到收信人的回复,这至关于消息反馈。上述例子中的信件就至关于Actor中的消息,Actor与Actor之间只能经过消息通讯。固然Actor模型比这要复杂的多,这里主要是简洁的阐述一下Actor模型的概念。github
对并发模型进行了更高的抽象
异步、非阻塞、高性能的事件驱动编程模型
轻量级事件处理(1GB内存可容纳百万级别个Actor)
为何Actor模型是一种处理并发问题的解决方案?
编程
一开始我也不怎么理解,脑子里的一向思惟是处理并发问题就是如何保证共享数据的一致性和正确性,为何会有保持共享数据正确性这个问题呢?无非是咱们的程序是多线程的,多个线程对同一个数据进行修改,若不加同步条件,势必会形成数据污染。那么咱们是否是能够转换一下思惟,用单线程去处理相应的请求,可是又有人会问了,如果用单线程处理,那系统的性能又如何保证。Actor模型的出现解决了这个问题。bash
Actor模型概图
:网络
从上图中咱们能够看到,Actor与Actor以前只能用消息进行通讯,当某一个Actor给另一个Actor发消息,消息是有顺序的,你只须要将消息投寄的相应的邮箱,至于对方Actor怎么处理你的消息你并不知道,固然你也可等待它的回复。多线程
JVM中的Actor有如下几个特色:并发
每一个Actor都有对应一个邮箱
Actor是串行处理消息的
Actor中的消息是不可变的
其实只从上面一些描述来看,并不能看出Actor在处理并发问题上的有什么优点。框架
但我总结了两点:简化并发编程
,提高程序性能
异步
咱们一开始说过并发致使最大的问题就是对共享数据的操做,咱们在面对并发问题时多采用的是 用锁去保证共享数据的一致性,但这一样也会带来其余相关问题,好比要去考虑锁的粒度(对方法,程序块等),锁的形式(读锁,写锁等)等问题,这些问题对并发程序来讲是相当重要的,但一个初写并发程序的程序员来讲,每每不能掌控的很好,这无疑给程序员在编程上提升了复杂性,并且还不容易掌控,但使用Actor就不致使这些问题,首先Actor的消息特性就以为了在与Actor通讯上不会有共享数据的困扰,另外在Actor内部是串行处理消息的,一样不会对Actor内的数据形成污染,用Actor编写并发程序无疑大大下降了编码的复杂度。
咱们以前说过既然用单线程处理,那如何保证程序的性能?首先Actor是很是轻量级的,你能够再程序中建立许多个Actor,并且Actor是异步的,那么如何利用它的这个特性呢,咱们要作的就是把相应的并发事件尽量的分割成一个个小的事件,让每一个Actor去处理相应的小事件,充分去利用它异步的特色,来提高程序的性能。
其实Scala中原生的Actor并不能完成不少事,不是一套完整的并发解决方案,不适合用于生产环境,好比错误恢复,状态持久化等,因此在较新版本的Scala类库中,Akka包已经取代了原生的Actor。
那下面咱们来简单说说Akka吧,Akka做为一套成熟的并发解决方案,已经被业界大量采用,尤为是在金融,游戏等领域,Akka中的容错机制,持久化,远程调用,日志等都是很重要的模块,这些内容都会在这个系列的后续文章里一一讲解。下面就以一个入门Akka程序来结束本篇文章吧。如今咱们假设有一个家居机器人,咱们只须要给它发送消息它便会帮咱们处理相应的事情,如今咱们用程序来模拟这个场景:源码连接
本示例使用Scala语言,构建工具为SBT,IDE为IntelliJ IDEA.
1.首先建立一个基于SBT的Scala工程
build.sbt
配置:
name := "Example_01"
version := "1.0"
scalaVersion := "2.11.8"
val akkaVersion = "2.4.16"
libraryDependencies +=
"com.typesafe.akka" %% "akka-actor" % akkaVersion
复制代码
2.咱们来定义一些消息:
trait Action{
val message: String
val time: Int
}
case class TurnOnLight(time: Int) extends Action { // 开灯消息
val message = "Turn on the living room light"
}
case class BoilWater(time: Int) extends Action { // 烧水消息
val message = "Burn a pot of water"
}
复制代码
3.咱们利用Actor来实现一个模拟机器人:
class RobotActor extends Actor {
val log = Logging(context.system, this)
def receive: Receive = { //机器人接受指令
case t: TurnOnLight => log.info(s"${t.message} after ${t.time} hour")
case b: BoilWater => log.info(s"${b.message} after ${b.time} hour")
case _ => log.info("I can not handle this message")
}
}
复制代码
4.咱们去测试这个机器人:
object Example_01 extends App {
val actorSystem = ActorSystem("robot-system")
val robotActor = actorSystem.actorOf(Props(new RobotActor()), "robotActor") //建立一个机器人
robotActor ! TurnOnLight(1) //给机器人发送一个开灯命令
robotActor ! BoilWater(2) //给机器人发送一个烧水命令
robotActor ! "who are you" //给机器人发送一个任意命令
actorSystem terminate ()
}
复制代码
5.运行结果
[INFO] [03/19/2017 13:48:05.622] [robot-system-akka.actor.default-dispatcher-4] [akka://robot-system/user/robotActor] Turn on the living room light after 1 hour
[INFO] [03/19/2017 13:48:05.622] [robot-system-akka.actor.default-dispatcher-4] [akka://robot-system/user/robotActor] Burn a pot of water after 2 hour
[INFO] [03/19/2017 13:48:05.622] [robot-system-akka.actor.default-dispatcher-4] [akka://robot-system/user/robotActor] I can not handle this message
复制代码
上面是一个很是简单的Akka例子,咱们首先建立了一个机器人的Actor,而后经过向它发送不一样指令,让它根据指令去作相应的事情,你们能够本身尝试去写一写类似的例子。
这篇就先到这里了,下一篇主要给你们讲讲Akka中Actor的分层结构。