定义一个 Actor 类

要定义自己的Actor类,需要继承 Actor 并实现receive 方法.

receive 方法需要定义一系列 case 语句(类型为 PartialFunction[Any, Unit]) 来描述你的Actor能够处理哪些消息,以及如何进行处理。

如下例:

  1. import akka.actor.Actor
  2. import akka.actor.Props
  3. import akka.event.Logging
  4. class MyActor extends Actor {
  5. val log = Logging(context.system, this)
  6. def receive = {
  7. case "test" ⇒ log.info("received test")
  8. case _ ⇒ log.info("received unknown message")
  9. }
  10. }

需要提供一个接受的所有消息的模式匹配规则,如果你希望处理未知的消息,你需要象上例一样提供一个缺省的case分支。否则会有一个 akka.actor.UnhandledMessage(message, sender, recipient) 被发布到 Actor系统(ActorSystem)‘的 事件流(EventStream)中。

发送消息

向actor发送消息是使用下列方法之一。

  • ! 意思是“fire-and-forget”, e.g. 异步发送一个消息并立即返回。也称为 tell.
  • ? 异步发送一条消息并返回一个 Future代表一个可能的回应。也称为 ask.

每一个消息发送者分别保证自己的消息的次序.

Tell: Fire-forget

这是发送消息的推荐方式。 不会阻塞地等待消息。它拥有最好的并发性和可扩展性。

  1. actor ! "hello"

如果是在一个Actor中调用 ,那么发送方的actor引用会被隐式地作为消息的 sender: ActorRef 成员一起发送. 目的actor可以使用它来向原actor发送回应, 使用 sender ! replyMsg.

如果 是从Actor实例发送的, sender成员缺省为 deadLetters actor 引用。

Ask: Send-And-Receive-Future

ask 模式既包含actor也包含future, 所以它是作为一种使用模式,而不是ActorRef的方法:

  1. import akka.pattern.{ ask, pipe }
  2. case class Result(x: Int, s: String, d: Double)
  3. case object Request
  4. implicit val timeout = Timeout(5 seconds) // 下面的 `?` 会用到
  5. val f: Future[Result] =
  6. for {
  7. x ← ask(actorA, Request).mapTo[Int] // 直接调用
  8. s ← actorB ask Request mapTo manifest[String] // 隐式转换调用
  9. d ← actorC ? Request mapTo manifest[Double] // 通过符号名调用
  10. } yield Result(x, s, d)
  11. f pipeTo actorD // .. 或 ..
  12. 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处理消息发生异常时自动完成。

  1. try {
  2. val result = operation()
  3. sender ! result
  4. } catch {
  5. case e: Exception ⇒
  6. sender ! akka.actor.Status.Failure(e)
  7. throw e
  8. }

如果一个actor没有完成future, 它会在超时时限到来时过期, 以 AskTimeoutException来结束. 超时的时限是按下面的顺序和位置来获取的:

  1. 显式指定超时:
  1. import akka.util.duration._
  2. import akka.pattern.ask
  3. val future = myActor.ask("hello")(5 seconds)
  1. 提供类型为 akka.util.Timeout的隐式参数, 例如,
  1. import akka.util.duration._
  2. import akka.util.Timeout
  3. import akka.pattern.ask
  4. implicit val timeout = Timeout(5 seconds)
  5. val future = myActor ? "hello"

参阅 Futures (Scala) 了解更多关于等待和查询future的信息。

FutureonComplete, onResult, 或 onTimeout 方法可以用来注册一个回调,以便在Future完成时得到通知。从而提供一种避免阻塞的方法。

警告

在使用future回调如 onComplete, onSuccess, and onFailure时, 在actor内部你要小心避免捕捉该actor的引用, i.e. 不要在回调中调用该actor的方法或访问其可变状态。这会破坏actor的封装,会引用同步bug和race condition, 因为回调会与此actor一同被并发调度。 不幸的是目前还没有一种编译时的方法能够探测到这种非法访问。 参阅: Actor与共享可变状态

akka实现的actor的更多相关文章

  1. Akka系列(二):Akka中的Actor系统

    前言......... Actor模型作为Akka中最核心的概念,所以Actor在Akka中的组织结构是至关重要,本文主要介绍Akka中Actor系统. 1.Actor系统 Actor作为一种封装状态 ...

  2. Akka简介与Actor模型

    Akka是一个构建在JVM上,基于Actor模型的的并发框架,为构建伸缩性强,有弹性的响应式并发应用提高更好的平台.本文主要是个人对Akka的学习和应用中的一些理解. Actor模型 Akka的核心就 ...

  3. akka设计模式系列-actor锚定

    actor锚定模式是指使用actorSelection对acor进行锚定的设计模式,也可以说是一个对actor的引用技巧.在某些情况下,我们可能需要能够根据Actor的path锚定对应的实例.简单来说 ...

  4. Akka简介与Actor模型(一)

    前言...... Akka是一个构建在JVM上,基于Actor模型的的并发框架,为构建伸缩性强,有弹性的响应式并发应用提高更好的平台.本文主要是个人对Akka的学习和应用中的一些理解. Actor模型 ...

  5. [翻译]AKKA笔记 - ACTOR生命周期 - 基本 -5

    原文地址:http://rerun.me/2014/10/21/akka-notes-actor-lifecycle-basic/ (请注意这了讨论的生命周期并不包括 preRestart 或者pos ...

  6. [Scala] akka actor编程(一)

    Akka基础 Akka笔记之Actor简介  Akka中的Actor遵循Actor模型.你可以把Actor当作是人.这些人不会亲自去和别人交谈.他们只通过邮件来交流.  1. 消息传递 2. 并发 3 ...

  7. Akka(2):Actor生命周期管理 - 监控和监视

    在开始讨论Akka中对Actor的生命周期管理前,我们先探讨一下所谓的Actor编程模式.对比起我们习惯的行令式(imperative)编程模式,Actor编程模式更接近现实中的应用场景和功能测试模式 ...

  8. Actor模型-Akka

    英文原文链接,译文链接,原文作者:Arun Manivannan ,译者:有孚 写过多线程的人都不会否认,多线程应用的维护是件多么困难和痛苦的事.我说的是维护,这是因为开始的时候还很简单,一旦你看到性 ...

  9. Akka系列---什么是Actor

    本文已.Net语法为主,同时写有Scala及Java实现代码 严肃的说,演员是一个广泛的概念,作为外行人我对Actor 模型的定义: Actor是一个系统中参与者的虚拟人物,Actor与Actor之间 ...

随机推荐

  1. 【Python⑤】python序列---list和tuple

    sequence 序列 sequence(序列)是一组有顺序的对象的集合.序列可以包含一个或多个元素,也可以没有任何元素. 我们之前所说的基本数据类型,都可以作为序列的对象.对象还可以是另一个序列.序 ...

  2. Request和response的用法总结

    Request 个我总结:只要记住 只要是有关于客户端请求的信息,都可以藉由它来取得,例如请求标头.请求方法.请求参数.使用者IP等等信息. 3.什么情况下为响应?什么情况下为请求? 简单一句话,请求 ...

  3. Eclipse智能提示及快捷键

    1.java智能提示 (1). 打开Eclipse,选择打开" Window - Preferences". (2). 在目录树上选择"Java-Editor-Conte ...

  4. 114 的 dns 的解析测试

    114 的 dns 号称使用  BGP Global AnyCast 技术多点部署 的方式, 可以将用户请求导向到"就近"的服务器,理论上是可以得到域名网络就近解析的IP的,所以将 ...

  5. Winform 支持高清屏(High DPI) 设置

    http://www.cnblogs.com/weiym/p/3555068.htmlhttp://crsouza.com/2015/04/how-to-fix-blurry-windows-form ...

  6. Java泛型学习笔记 - (六)泛型的继承

    在学习继承的时候, 我们已经知道可以将一个子类的对象赋值给其父类的对象, 也就是父类引用指向子类对象, 如: Object obj = new Integer(10); 这其实就是面向对象编程中的is ...

  7. SQLserver技巧

    (1) SQL标记  连接连个表然后用 DATA  COMPAREDATA进行区分select 'DATA ' ,'列名1','列名2','列名3' from  表 union select 'COM ...

  8. shell 简单的比大小脚本

    #!/bin/bash echo "第一个数字" read a echo "第二个数字" read b if [ $a -gt $b ] then echo & ...

  9. SSH面试题收藏

    Hibernate工作原理及为什么要用? 原理: 1. 读取并解析配置文件2. 读取并解析映射信息,创建SessionFactory3. 打开Sesssion4. 创建事务Transation5. 持 ...

  10. MVC 支持同名路由,不同命名空间

    有时候我们会碰到两个项目合在一起,那么必然会碰到两个同名的controller,其实MVC在注册路由,添加Route的时候可以指定当前规则解析那个命名空间下的所有Controller. 注:Contr ...