Search code examples
scalaakkaactorexecutioncontext

scala akka - Number of threads grows indefinitly even when actors are killed


I'm creating an actor per unit of work. Each actor creates a thread pool. when the work is completed it messages its sender which will inturn send the child actor a poison pill

I noticed that the number of threads in the jvm process is still growing indefinitly even though the child actors are "killed"

Example

class ParentActor (...) extends Actor {
 ....
 ....

 val childActor = props(...child actor props...)
 val resultFuture = childActor ? "do some work"
 ...
 resultFuture onComplete {
   ...
   childActor ! PoisonPill // "kill" the child actor
 }

class ChildActor(...) extends Actor {
  val executionContext: ExecutionContextExecutor = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(10))
...

  receive {
    ...
    sender ! "done"
  }

  override def postStop() {
    println("post stop called") // the actor prints this
  }
}

Shouldn't the actor be GCd along with its threads?


Solution

  • Thread pools don't get automatically garbage collected. See the docs for the Java ThreadPoolExecutor

    https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/ThreadPoolExecutor.html

    A pool that is no longer referenced in a program AND has no remaining threads may be reclaimed (garbage collected) without being explicitly shutdown.

    But since you are creating a fixed pool, it will never have "no remaining threads". So it will never be collected by the JVM, even though the child actor is stopped.

    You could implement a cleanup method in a postStop, calling shutdownNow(). But, as Thilo points out, managing thread pools in child actors is pretty weird. You don't explain why you want to do that, but I'd consider letting Akka manage your threads.