akka实现的actor
定义一个 Actor 类
要定义自己的Actor类,需要继承 Actor 并实现receive 方法.
receive 方法需要定义一系列 case 语句(类型为 PartialFunction[Any, Unit]) 来描述你的Actor能够处理哪些消息,以及如何进行处理。
如下例:
- import akka.actor.Actor
- import akka.actor.Props
- import akka.event.Logging
- class MyActor extends Actor {
- val log = Logging(context.system, this)
- def receive = {
- case "test" ⇒ log.info("received test")
- case _ ⇒ log.info("received unknown message")
- }
- }
需要提供一个接受的所有消息的模式匹配规则,如果你希望处理未知的消息,你需要象上例一样提供一个缺省的case分支。否则会有一个 akka.actor.UnhandledMessage(message, sender, recipient) 被发布到 Actor系统(ActorSystem)‘的 事件流(EventStream)中。
发送消息
向actor发送消息是使用下列方法之一。
- ! 意思是“fire-and-forget”, e.g. 异步发送一个消息并立即返回。也称为 tell.
- ? 异步发送一条消息并返回一个 Future代表一个可能的回应。也称为 ask.
每一个消息发送者分别保证自己的消息的次序.
Tell: Fire-forget
这是发送消息的推荐方式。 不会阻塞地等待消息。它拥有最好的并发性和可扩展性。
- actor ! "hello"
如果是在一个Actor中调用 ,那么发送方的actor引用会被隐式地作为消息的 sender: ActorRef 成员一起发送. 目的actor可以使用它来向原actor发送回应, 使用 sender ! replyMsg.
如果 不 是从Actor实例发送的, sender成员缺省为 deadLetters actor 引用。
Ask: Send-And-Receive-Future
ask 模式既包含actor也包含future, 所以它是作为一种使用模式,而不是ActorRef的方法:
- import akka.pattern.{ ask, pipe }
- case class Result(x: Int, s: String, d: Double)
- case object Request
- implicit val timeout = Timeout(5 seconds) // 下面的 `?` 会用到
- val f: Future[Result] =
- for {
- x ← ask(actorA, Request).mapTo[Int] // 直接调用
- s ← actorB ask Request mapTo manifest[String] // 隐式转换调用
- d ← actorC ? Request mapTo manifest[Double] // 通过符号名调用
- } yield Result(x, s, d)
- f pipeTo actorD // .. 或 ..
- pipe(f) to actorD
上面的例子展示了将 ask 与 future上的 pipeTo 模式一起使用,因为这是一种非常常用的组合。 请注意上面所有的调用都是完全非阻塞和异步的: ask 产生 Future, 三个Future通过for-语法组合成一个新的Future,然后用 pipeTo 在future上安装一个 onComplete-处理器来完成将收集到的 Result 发送到其它actor的动作。
使用 ask 将会象 tell 一样发送消息给接收方, 接收方必须通过 sender ! reply 发送回应来为返回的 Future 填充数据. ask 操作包括创建一个内部actor来处理回应,必须为这个内部actor指定一个超时期限,过了超时期限内部actor将被销毁以防止内存泄露。
如果要以异常来填充future你需要发送一个 Failure 消息给发送方。这个操作不会在actor处理消息发生异常时自动完成。
- try {
- val result = operation()
- sender ! result
- } catch {
- case e: Exception ⇒
- sender ! akka.actor.Status.Failure(e)
- throw e
- }
如果一个actor没有完成future, 它会在超时时限到来时过期, 以 AskTimeoutException来结束. 超时的时限是按下面的顺序和位置来获取的:
- 显式指定超时:
- import akka.util.duration._
- import akka.pattern.ask
- val future = myActor.ask("hello")(5 seconds)
- 提供类型为 akka.util.Timeout的隐式参数, 例如,
- import akka.util.duration._
- import akka.util.Timeout
- import akka.pattern.ask
- implicit val timeout = Timeout(5 seconds)
- val future = myActor ? "hello"
参阅 Futures (Scala) 了解更多关于等待和查询future的信息。
Future的onComplete, onResult, 或 onTimeout 方法可以用来注册一个回调,以便在Future完成时得到通知。从而提供一种避免阻塞的方法。
警告
在使用future回调如 onComplete, onSuccess, and onFailure时, 在actor内部你要小心避免捕捉该actor的引用, i.e. 不要在回调中调用该actor的方法或访问其可变状态。这会破坏actor的封装,会引用同步bug和race condition, 因为回调会与此actor一同被并发调度。 不幸的是目前还没有一种编译时的方法能够探测到这种非法访问。 参阅: Actor与共享可变状态
akka实现的actor的更多相关文章
- Akka系列(二):Akka中的Actor系统
前言......... Actor模型作为Akka中最核心的概念,所以Actor在Akka中的组织结构是至关重要,本文主要介绍Akka中Actor系统. 1.Actor系统 Actor作为一种封装状态 ...
- Akka简介与Actor模型
Akka是一个构建在JVM上,基于Actor模型的的并发框架,为构建伸缩性强,有弹性的响应式并发应用提高更好的平台.本文主要是个人对Akka的学习和应用中的一些理解. Actor模型 Akka的核心就 ...
- akka设计模式系列-actor锚定
actor锚定模式是指使用actorSelection对acor进行锚定的设计模式,也可以说是一个对actor的引用技巧.在某些情况下,我们可能需要能够根据Actor的path锚定对应的实例.简单来说 ...
- Akka简介与Actor模型(一)
前言...... Akka是一个构建在JVM上,基于Actor模型的的并发框架,为构建伸缩性强,有弹性的响应式并发应用提高更好的平台.本文主要是个人对Akka的学习和应用中的一些理解. Actor模型 ...
- [翻译]AKKA笔记 - ACTOR生命周期 - 基本 -5
原文地址:http://rerun.me/2014/10/21/akka-notes-actor-lifecycle-basic/ (请注意这了讨论的生命周期并不包括 preRestart 或者pos ...
- [Scala] akka actor编程(一)
Akka基础 Akka笔记之Actor简介 Akka中的Actor遵循Actor模型.你可以把Actor当作是人.这些人不会亲自去和别人交谈.他们只通过邮件来交流. 1. 消息传递 2. 并发 3 ...
- Akka(2):Actor生命周期管理 - 监控和监视
在开始讨论Akka中对Actor的生命周期管理前,我们先探讨一下所谓的Actor编程模式.对比起我们习惯的行令式(imperative)编程模式,Actor编程模式更接近现实中的应用场景和功能测试模式 ...
- Actor模型-Akka
英文原文链接,译文链接,原文作者:Arun Manivannan ,译者:有孚 写过多线程的人都不会否认,多线程应用的维护是件多么困难和痛苦的事.我说的是维护,这是因为开始的时候还很简单,一旦你看到性 ...
- Akka系列---什么是Actor
本文已.Net语法为主,同时写有Scala及Java实现代码 严肃的说,演员是一个广泛的概念,作为外行人我对Actor 模型的定义: Actor是一个系统中参与者的虚拟人物,Actor与Actor之间 ...
随机推荐
- MongoDB副本集的实现与维护实战
1.建立MongoDB副本集 现利用一台机器完成MongoDB副本集的建立 机器1:127.0.0.1:27017 机器2:127.0.0.1:27018 机器3:127.0.0.1:27019 在D ...
- 编程key note
一些日常发现的code better的要点.不断更新. * #include <assert.h> 使用断言* 每个模块(文件)应该有一个唯一的一个前缀,模块导出的所有全局名字都应以此前缀 ...
- storm启动过程之源码分析
TopologyMaster: 处理拓扑的一些基本信息和工作,比如更新心跳信息,拓扑指标信息更新等 NimbusServer: ** * * NimbusServer work flow: 1. ...
- anguar.js tutorial demo
http://docs.angularjs.cn/tutorial angular 入门demo : PhoneCat Tutorial App 别人的DEMO(官方版):http://angular ...
- Shell脚本8种字符串截取方法总结
Linux 的字符串截取很有用.有八种方法. 假设有变量 var=http://www.aaa.com/123.htm. 1. # 号截取,删除左边字符,保留右边字符. 代码如下: echo ${va ...
- oracle中dual的使用
dual是一个虚拟表,用来构成select的语法规则,oracle保证dual里面永远只有一条记录.我们可以用它来做很多事情,如下:1.查看当前用户,可以在 SQL Plus中执行下面语句select ...
- jquery checkbox实例
<!DOCTYPE html><html> <head><meta charset="utf-8" /><title>& ...
- 一个Java复制目录的方法(递归)
/** * 将目标目录复制为指定目录(也可以用于复制文件) * @param src 源路径 * @param dest 目标路径 * @throws IOException */ public st ...
- zip压缩命令的使用
file命令可以查看文件的类型 tar类型 .tar gzip类型 .gz bzip2类型 .bz2 zip类型 .zip 如果一个压缩文件由tar命令解压的前提,2个条件 1.这个文件 ...
- 在WPF中获取DataGridTemplateColumn模板定义的内容控件
xaml格式描述: <DataGrid Name="dataGrid" Grid.Row="1" ItemsSource="{Binding}& ...