1. Introduction

Akka is a very popular actor toolkit in Scala and Java. Actors are thread-like lightweight units that do a particular computation. We can create as many actors as required. Once the computation is completed, we can stop these actors.

In this tutorial, we’ll look at different ways actors can be stopped.

2. Setup

First, let’s set up a simple project with Akka dependencies:

libraryDependencies ++= Seq(
  "com.typesafe.akka" %% "akka-actor" % "2.6.18",
  "com.typesafe.akka" %% "akka-testkit" % "2.6.18" % Test
)

3. Using stop() Method

We can use the stop() method on the ActorSystem to stop an actor. This will stop the actor once it completes the processing of the current message. All the remaining messages in the mailbox will be sent to DeadLetters. Let’s give it a try:

val system = ActorSystem("system") 
val actor = system.actorOf(Props(classOf[MessageProcessorActor])) actor ! Greet("Msg 1")
actor ! Greet("Msg 2")
actor ! Greet("Msg 3") 
system.stop(actor)

If the actor is stopped while processing the message Msg 1, it will suspend its mailbox and wait for the current processing to be completed. Once it is completed, the actor will be stopped, and the rest of the messages in the mailbox will be sent to DeadLetters. After the current actor is stopped, it will invoke its postStop() hook to clean up the resources.

If the stopped actor has any child actors, all the child actors will be notified. As soon as the current processing is done, all the child actors will also be stopped. After that, the parent actor will then be stopped. Therefore, the actors are stopped in a bottom-up way in the hierarchy.

Note that stopping the actor is an asynchronous process, which means the stop() method may be returned before the actor is completely stopped.

If one of the child actors is processing a long computation and cannot execute its stop messages, the entire hierarchy may get stuck.

We can also stop an actor from within itself using the stop() method from ActorContext:

context.stop(self)

4. Using PoisonPill Message

Another way to stop an actor is by sending a special type of message, called PoisonPill, to the actor. This message acts like any other message and will be queued up in the actor’s mailbox. When the actor finds this message, it will stop itself. That means all the messages before the PoisonPill will be processed normally. The messages which came after the PoisonPill will be sent to DeadLetters.

Let’s send the PoisonPill to the actor:

actor ! PoisonPill

5. Using gracefulStop

Another way of stopping an actor is using the gracefulStop() method. This method will return a Future response. When the actor completes processing and terminates within the configured timeout, it will return with success. If it exceeds more time, the response will be a failed Future. This is especially useful when we want to stop the actors in an orderly fashion:

try {
  val stopped: Future[Boolean] = gracefulStop(actor, 5 seconds, PoisonPill) 
  Await.result(stopped, 6 seconds)
} catch { 
  // the actor wasn't stopped within 5 seconds 
  case e: akka.pattern.AskTimeoutException => 
}

6. Using Kill

We can also stop an actor using the Kill message. As soon as an actor gets a Kill message, it will complete the current processing message and throws an ActorKilledException. Hence, the supervisor actor will get notified and handle the situation based on the configured supervision strategy.

We can send the kill message as:

actor ! Kill

7. Conclusion

In this article, we have looked at different ways in which an Akka actor can be stopped.

As always, the sample code is available over on GitHub.


« 上一篇: Scala 中的 Break 语句
» 下一篇: Scala 中的类型推断