如何在斯卡拉清理我死去的演员

use*_*048 5 scala actor

嗨我使用scala(2.8.1)来实现一个使用actor的耗时任务处理程序,但是,我无法在运行单元测试时清理它,所以我的单元测试永远挂起.

我怎么称呼方法是:

  val configs = new ProjectsConfig("XXXXXXXXXXXXX")
  try {
    configs.start
    configs.init//time consuming stuff
  } finally {
    configs.destory
    configs.stop
  }
Run Code Online (Sandbox Code Playgroud)

我打算做的是保持actor的引用并在每个on上调用exit,代码片段如下:

  • init,初始化actor并保持每个actor的引用.
  • destory,呼叫每个演员的退出.
  • 停止,呼叫这个演员的退出.

但是,似乎效果不佳.在这种情况下如何清理所有演员?

class ProjectsConfig(val url: String) extends Actor {
  private var actors: List[Actor] = List()
  private object Stop

  def init = {
    val caller = this;
    for (projectConfig <- list) {
      val myActor: Actor = actor {
        caller ! projectConfig.instantiate
      }
      actors = actors ::: List(myActor)
    }
  }

  def act() {
    while (true) {
      receive {
        case project: Project =>
          Projects.update(project)
        case Stop => exit()
      }
    }
  }

  def destory {
    for (actor <- actors) {
      try {
        actor ! exit
      } catch {
        case e => System.out.println(e.printStackTrace)
      }
    }
  }

  def stop() {
    this ! Stop
  }
Run Code Online (Sandbox Code Playgroud)

Vas*_*iuk 3

1)根据你的具体情况,我会简化

val myActor: Actor = actor {
caller ! projectConfig.instantiate
}
Run Code Online (Sandbox Code Playgroud)

就只是caller ! projectConfig.instantiate. 您已经从参与者的子系统进行了调用,因此不需要额外的包装。

除此之外,虽然通常建议从 actor 的环境中调用 actor(生成调用),但这根本不是“必须”的(如果您直接在非 actor 环境中调用 actor,也不会发生任何邪恶情况)。就您而言,包装调用反而会增加问题(样板文件和不一致)。

2)实际发生的情况actor ! exit是actor ! Actor.exit(假设您有通配符导入Actor)。此代码在尝试计算 时会引发异常Actor.exit,并且不会向参与者发送任何内容。为了停止 actor,您必须调用exit它的实例。它可以通过消息发送来完成,这将调用 protected exit:

actor{
  loop{
     react{
        case `exit => exit('stop)
     }
  }
}
Run Code Online (Sandbox Code Playgroud)