Actor 简易教程
来源:互联网 发布:怎么使用 java工作流 编辑:程序博客网 时间:2024/05/02 00:59
Akka Actor 学习
Actor System
每个Actor 独立运行,Actor间只有通过消息传递来communication.- ! 传递消息 并立即返回- ? 传递消息 返回一个变量future用来表示可能的回复.
每个Actor 有一个mailbox来接受信息, 默认的接受方式是FIFO.
Akka框架保证每个Actor的实例拥有一个轻量级线程, 并保证每次处理一个消息.
用户可以通过Akka Acotr API 获取以下信息:- sender 当前处理消息的发送Actor.- context 获取当前Actor的关于context的信息和方法- supervisionStrategy 使用此类来定义错误恢复策略- self 当前Actor本身
一下通过一个count文本中word数的例子来讲解Actor的使用方法:首先将problem分解为两个子任务, 1. 子任务count每行的word数; 2. 父任务累加每个子任务的count和.
父任务从文本读取并将每行发送给一个子任务, 子任务收到一行后计算word量并发送count给父任务.
case class ProcessStringMsg(string: String)case class StringProcessedMsg(words: Integer)class StringCounterActor extends Actor { def receive = { case ProcessStringMsg(string) => { val wordsInLine = string.split(" ").length sender ! StringProcessedMsg(wordsInLine) } case _ => println("Error: message not recognized") }}
子任务actor任务很简单,消耗一个ProcessStringMsg 从中解压出字符串然后统计字符串的word个数, 再使用 ! 将wordsInLine回传给sender.
1. case class StartProcessFileMsg()2.3. class WordCounterActor(filename: String) extends Actor {4. 5. private var running = false6. private var totalLines = 07. private var linesProcessed = 08. private var result = 09. private var fileSender: Option[ActorRef] = None10. 11. def receive = {12. case StartProcessFileMsg() => {13. if (running) {14. // println just used for example purposes;15. // Akka logger should be used instead16. println("Warning: duplicate start message received")17. } else {18. running = true19. fileSender = Some(sender) // save reference to process invoker20. import scala.io.Source._21. fromFile(filename).getLines.foreach { line =>22. context.actorOf(Props[StringCounterActor]) ! ProcessStringMsg(line)23. totalLines += 124. }25. }26. }27. case StringProcessedMsg(words) => {28. result += words29. linesProcessed += 130. if (linesProcessed == totalLines) {31. fileSender.map(_ ! result) // provide result to process invoker32. }33. }34. case _ => println("message not recognized!")35. }36. }
父任务收到StartProcessFileMsg后读取file并对每行开启一个Actor, 将该行发送给该Actor. 收到StringProcessedMsg后累加到总count中, 收集到所有子任务的结果后将总count回传到开启发送StartProcessFileMsg的Actor.
使用一下代码来开启整个app.
object Sample extends App { import akka.util.Timeout import scala.concurrent.duration._ import akka.pattern.ask import akka.dispatch.ExecutionContexts._ implicit val ec = global override def main(args: Array[String]) { val system = ActorSystem("System") val actor = system.actorOf(Props(new WordCounterActor(args(0)))) implicit val timeout = Timeout(25 seconds) val future = actor ? StartProcessFileMsg() future.map { result => println("Total number of words " + result) system.shutdown } }}
使用 ? 来获得回传的消息.
错误恢复
再actor 系统中,每个actor都是其子actor的监护人.也就是说如果一个actor遇到了错误, 它会暂停自己和它所有的子actor.Actor处理又其孩子传上来的exceptions所使用的策略叫做监护人策略.当错误信息到达监护人时,可以采取一下几种策略:- 恢复子actor以及actor的子actor, 保持它的内部状态.- 重启子actor, 清空它的内部状态.- 永久停止子actor.- 停止自己, 并将错误信息往上传.
actor可以决定将策略应用到错误的子actor上还是应用到所有子actor上.- OneForOneStrategy: 只对错误的子actor生效.- AllForOneStrategy: 对所有子actor生效.
以下是一个例子:
import akka.actor.OneForOneStrategyimport akka.actor.SupervisorStrategy._import scala.concurrent.duration._override val supervisorStrategy = OneForOneStrategy() { case _: ArithmeticException => Resume case _: NullPointerException => Restart case _: IllegalArgumentException => Stop case _: Exception => Escalate }
位置透明
Akka 体系支持位置透明, 使得actor不需在意消息发送者来自哪里. 消息发送者跟消息接受者既可以在同一个JVM/节点, 也可以不在同一个JVM/节点上. 当在不同的节点上时, 消息必须继承Serializable.程序员唯一需要做的就是配置application.conf文件, 以下是这个文件的一个示例:
akka { actor { provider = "akka.remote.RemoteActorRefProvider" } remote { transport = "akka.remote.netty.NettyRemoteTransport" netty { hostname = "127.0.0.1" port = 2552 } }}
需要注意的是, 尽可能的将消息定义为imutable, 以防止出现不可以预计的错误.
- Actor 简易教程
- Actor-Critic强化学习教程
- 简易教程
- Actor
- Actor
- Actor
- Actor
- akka学习教程(四) actor生命周期
- ERP简易教程
- ERP简易教程
- XML简易教程之一
- Reporting Service 简易教程
- Atlabs简易教程
- Java Bean简易教程
- Ruby程序设计简易教程
- XML schema 简易教程
- IDA简易教程
- WINDBG Script简易教程
- 【2】Quick-Cocos2d-x3.3Coinflip示例分析之MenuScene、MoreGamesScene
- cocos2d-x3.2中如何优化Cocos2d-X游戏的内存
- 回文判断
- Linux常用命令(十五) - which
- 正则表达式学习参考
- Actor 简易教程
- Linux常用命令(十六) - whereis
- 如何在Node项目中引用和发布自己写的Module
- 大-小顶混合堆的实现与应用(a min-max heap)
- python(1)
- erlang四大behaviour之二-gen_fsm
- Linux常用命令(十七) - locate
- LoadRunner Socket协议学习
- DSS (LCD+HDMI) OMAP4460 第十章