演员实例数

yjs*_*hen 1 scala actor akka

我是 akka-actor 的新手,对一些问题感到困惑:

  1. 当我创建一个actorSystem,并使用actorOf(Props(classOf[AX], ...)) 在main 方法中创建actor 时,我的actor AX 有多少个实例?
  2. 如果 Q1 的答案只有一个,这是否意味着我在 AX 演员类的定义中创建的任何数据结构只会出现在一个线程中,我不应该担心并发问题?
  3. 如果我的演员的一个动作(接收方法中的一个案例)是一项耗时的任务并且需要很长时间才能完成怎么办?我的单个 Actor 实例在完成该任务之前不会响应吗?
  4. 如果 Q3 的答案是正确的,我应该怎么做才能防止我的演员没有回应?我应该启动另一个线程并向它发送另一条消息直到完成任务吗?有没有我应该遵循的最佳实践?

Joo*_*oer 5

  1. 是的,每次调用“actorOf”方法时,actor 系统只会创建 1 个 actor 实例。但是,当使用路由器时,可以创建 1 个路由器,将负载分散到任意数量的参与者。因此,在这种情况下,可以构造多个实例,但“通常”使用 actorOf 只会创建 1 个实例。

  2. 是的,在 actor 内您不必担心并发性,因为 Akka 保证任何 actor 一次只处理 1 条消息。您必须注意不要以某种方式从 actor 外部的代码中改变 actor 的状态。因此,无论何时公开角色状态,请始终使用不可变类来执行此操作。案例类非常适合这一点。但在从 actor 内部完成 Future 时,也要注意修改 actor 状态。由于 Future 在它自己的线程上运行,当 Future 完成并且参与者同时处理下一条消息时,您可能会遇到并发问题。Actor 一次在 1 个线程上执行,但每次执行 Actor 时这可能是一个不同的线程。

  3. Akka 是一个高度并发和分布式的框架,一切都是异步和非阻塞的,你必须在你的应用程序中做同样的事情。Scala 和 Akka 提供了几种解决方案来做到这一点。每当你在一个actor中有一个耗时的任务时,你可能会为此目的将耗时的任务委托给另一个actor,使用Futures或使用Scala的“async/await/blocking”。使用“阻塞”时,您会向编译器/运行时提示阻塞操作已完成,运行时可能会启动额外的线程以防止线程饥饿。在斯卡拉并发编程的书是学习这个东西一个很好的指南。另请查看并发包 ScalaDocsNeophyte 's Guide to Scala. 如果演员真的必须等待耗时的任务完成,那么是的,您的演员只能在完成后做出响应。但这是一种非常“请求-响应”的思维方式。尝试摆脱这种情况。参与者还可以立即响应指示任务已开始并在任务完成后发送附加消息。对于耗时的任务,请务必使用不同的线程池,这样 ActorSystem 就不会被阻塞,因为它的所有可用线程都被耗时的任务用光了。对于 Future,您可以提供一个单独的 ExecutionContext(不要为此使用 ActorSystem 的 Dispatch 上下文!),但是通过 Akka 的配置,您还可以将某些 Actor 配置为在不同的线程池上运行。

  4. 见 3。

成功!