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

时间:2011-04-30 02:01:16

标签: 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
  }

我打算做的是保持演员的引用并在每个上面调用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
  }

1 个答案:

答案 0 :(得分:3)

1)在您的具体情况下,我会简化

val myActor: Actor = actor {
caller ! projectConfig.instantiate
}

caller ! projectConfig.instantiate。你已经从演员的子系统打电话了,所以不需要额外的包装。

除此之外,虽然通常建议从演员的环境中召唤演员(产生电话),但根本不是“必须”(如果你打电话给演员直接在一个非演员env)。在您的情况下,包装调用会增加问题(样板和不一致)。

2)actor ! exit中实际发生的事件是actor ! Actor.exitassuming that you have a wildcard import on Actor)。此代码抛出一个异常,试图评估Actor.exit,并且没有任何内容发送给actor。要停止actor,您必须在其实例上调用exit。它可以通过消息发送来完成,它将调用受保护的exit

actor{
  loop{
     react{
        case `exit => exit('stop)
     }
  }
}