Hi I am using scala(2.8.1) to implement a time-consuming task handler using actor, however, I am not able to clean it up when running my unit tests, so my unit tests hung forever.
how I call the method is:
val configs = new ProjectsConfig("XXXXXXXXXXXXX")
try {
configs.start
configs.init//time consuming stuff
} finally {
configs.destory
configs.stop
}
What I plan to do is to keep the actors' reference and call exit on each on, the code snippet is like this:
- init, initialize the actors and keep the reference of each actor.
- destory, call exit on each actor.
- stop, call exit on 开发者_运维技巧this actor.
however, it seems not working well. how to clean all actors in this case?
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) In your specific case, I would simplify
val myActor: Actor = actor {
caller ! projectConfig.instantiate
}
to just caller ! projectConfig.instantiate
. You're already making a call from the actor's sub-system, so an additional wrapping is not needed.
Besides that, though it's generally recommended to call actors from the actors' environment (spawning the call), it's not a "must" at all (and no evil will happen, if you call the actor directly in a non-actor env). In your case, wrapping the calls rather adds problems (boilerplate and inconsistencies).
2) What's actually happening in actor ! exit
is actor ! Actor.exit
(assuming that you have a wildcard import on Actor
). This code throws an exception attempting to evaluate Actor.exit
, and nothing is sent to the actor. In order to stop the actor, you must call exit
on its instance. It can be done through a message-sending, that will call a protected exit
:
actor{
loop{
react{
case `exit => exit('stop)
}
}
}
精彩评论