Search code examples
scalaakkaactor

Terminates all other actors once one actor finishes its work


I am pretty new to scala and akka. I wonder to ask terminates all other actors once one of the actor finishes its work.

The basic structure of the code is as below. There is a Master who takes in charge of 5 workers, which are generated by a RoundRobinPool. Every worker is doing some work and will send the result back to the Master. What I need to realize is to let the Master to terminate all other workers once one of them finishes its work and send it back to the Master. The master then will send some relative value to the main function and then the whole program terminates.

Any idea how to implement this?

//Code:    
object X{
    sealed trait Message 
    case class Result() extends Message 
    case class Work() extends Message
    case class Result() extends Message 
    case class Totalresult() extends Message
    class Worker extends Actor{
        def receive={
           case Work =>
           sender ! Result}
    }//End of class Worker         
    class Master(nrOfWorkers: Int) extends Actor{
        val workerRouter =context.actorOf(RoundRobinPool(nrOfWorkers).props(Props[Worker]))) 
        def receive={
            case Calculate => calculateSender=sender                   
            case Result => calculateSender ! Totoalresult()
        }
    }//End of class Master  
    def main(args: String) {
       val system =ActorSystem("mysystem")
       val master=system.actorOf(Props(new Master(5),name="master")  
       val future=master ? Calculate
    }  
}

Solution

  • One of the major supervisionary aspects of Akka is that a given actor is considered responsible for its children. In this case, that means that the death of the "Master" actor will automatically result in termination of all its children, so all you really need to do is have the "Master" actor terminate itself. This can be done in a number of ways, such as through a Kill or or PoisonPill message to itself - eg, adding the line: self ! PoisonPill straight after sending the TotalResult message back to calculateSender.

    Note that in the particular scenario you have described in your code, you set up to receive a future of a result in your main, but don't include any processing (eg. an onComplete call, or using Await) of that result. You could, in such processing, include a call to system.shutdown() rather than having the "Master" terminate itself, which would then terminate all the actors as part of the shutdown process - just be sure to call that only after the future (and hence the actor effort behind it) has completed.

    PS: see this question for more info about the differences between the different ways of terminating an actor.