您好 我使用scala(2.8.1)来使用actor实现一个耗时的任务处理程序,但是,我在运行单元测试时无法清理它,所以我的单元测试永远挂起。
我如何调用该方法:
val configs = new ProjectsConfig("XXXXXXXXXXXXX")
try {
configs.start
configs.init//time consuming stuff
} finally {
configs.destory
configs.stop
}
我打算做的是保持演员的引用并在每个上面调用exit,代码片段是这样的:
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
}
答案 0 :(得分:3)
1)在您的具体情况下,我会简化
val myActor: Actor = actor {
caller ! projectConfig.instantiate
}
到caller ! projectConfig.instantiate
。你已经从演员的子系统打电话了,所以不需要额外的包装。
除此之外,虽然通常建议从演员的环境中召唤演员(产生电话),但根本不是“必须”(如果你打电话给演员直接在一个非演员env)。在您的情况下,包装调用会增加问题(样板和不一致)。
2)actor ! exit
中实际发生的事件是actor ! Actor.exit
(assuming that you have a wildcard import on Actor
)。此代码抛出一个异常,试图评估Actor.exit
,并且没有任何内容发送给actor。要停止actor,您必须在其实例上调用exit
。它可以通过消息发送来完成,它将调用受保护的exit
:
actor{
loop{
react{
case `exit => exit('stop)
}
}
}