How to wait for Akka actor system to terminate?

2020-05-20 08:12发布

问题:

I need to start Akka (2.0) actor system, send in some messages, then wait for it to do heavy lifting. After that, I need to do something unrelated to those actors.

I tried to wait for all actors to stop with following code:

val system = new ActorSystem("parallelRunners")
val master = system.actorOf(Props[Master])
master ! Start
system.awaitTermination // <-- hangs here

All actors kill themselves via self ! PoisonPill. What am I doing wrong?

回答1:

In Akka 2.4.1 for scala 2.11 it appears to be different again.

system.awaitTermination() is deprecated and the docs instruct us to use Await.result(system.whenTerminated, timeout) instead.

As 203 said, system.terminate is still the way to terminate the system.

Here is some example code I used:

val actorSystem = ActorSystem("ActorSystem")
val myActors = actorSystem.actorOf(Props[MyActor].withRouter(RoundRobinPool(10)), "MyActors")
rainbows.foreach(rainbow => myActors ! rainbow)
Await.ready(actorSystem.whenTerminated, Duration(1, TimeUnit.MINUTES))

Then in the MyActor class I have the line context.system.terminate()



回答2:

As of Akka 2.4, you should use system.awaitTermination() which returns a Future[Terminated] you can wait for.

In order to terminate the system, you should use ActorSystem.terminate (e.g. context.system.terminate() from within an actor when it is finished.

Source: Release Notes



回答3:

Just a side note for those running into this question for its title: Apparently, Akka 2.5 does not support actorSystem.awaitTermination anymore. Reason being why might be Akka's philosophy of avoiding any blocking calls. Instead, actorSystem.registerOnTermination(...) can be used as a non-blocking way to do actions while an ActorSystem is being shutdown.

Nonetheless, you can still wait for your actor system to complete via a Future provided by ActorSystem.whenTerminated:

val system = new ActorSystem("parallelRunners")
val master = system.actorOf(Props[Master])
master ! Start

import scala.concurrent.Await
import scala.concurrent.duration._
Await.ready(system.whenTerminated, 365.days)


回答4:

I found the solution - just call system.shutdown from the master actor:

context.system.shutdown


回答5:

You can also kill the ActorSystem from the main thread by using system.shutdown. But that operation is asynchronous. You only need to use system.awaitTermination if you need to block the main thread until it completes. If your parallelRunners return something useful for the rest of the program, then it would probably be easiest to not block and continue your program.



回答6:

in Akka 2.3.9, it seems that shutting down an actor system and waiting for it to shut down is a two step process:

  1. Initiate the shutdown: actorSystem.shutdown
  2. Wait for its termination in a blocking manner: actorSystem.awaitTermination

As an alternative to step (2), possibly (haven't tested these alternatives) you may alternatively poll on isTerminated or use registerOnTermination for running some code when it's terminated. So it is worth going through the comments of akka.actor.ActorSystem to fathom and choose between these methods for your implementation.

Perhaps I'm missing other options about the API (?) as Future return values could have been nicer.



回答7:

How about:

import scala.concurrent.Await
import scala.concurrent.duration._

Await.ready(system.terminate(), 5.seconds)

terminate returns a Future:

def terminate(): Future[Terminated]

and you can just await completion of this future.



标签: scala akka