Scala 进程未正确关闭

问题描述

我有一个模式来启动一个外部程序,如果它没有及时完成,就杀死它:

    val process = command.run(false)
    val future = Future(blocking {
      process.exitValue()
    })
    val ret = try {
      Await.result(future,duration.Duration(TIME,duration.SECONDS))
    } catch {
      case _: TimeoutException =>
        process.destroy()
    }

但是,出了点问题,进程(或线程?)不断堆积。当我开始时,我有大约 70 个线程(根据 Thread.getAllStackTraces.keySet().size)。运行几个小时后,我的内存超过 310,应用程序崩溃,因为所有内存都用完了。

线程列表如下所示:

3  finalizer  waiting
173  scala-execution-context-global-173  waiting
555  scala-execution-context-global-555  waiting
762  scala-execution-context-global-762  waiting
1278  process reaper  blocked
1280  simple-error-spawn-thread-760  runnable
1651  simple-output-spawn-thread-943  runnable
636  scala-execution-context-global-636  waiting
86  process reaper  blocked
153  scala-execution-context-global-153  waiting
1593  simple-output-spawn-thread-913  runnable
588  scala-execution-context-global-588  waiting
769  scala-execution-context-global-769  waiting
1500  simple-output-spawn-thread-871  runnable
352  scala-execution-context-global-352  waiting
1245  simple-output-spawn-thread-743  runnable
1793  simple-error-spawn-thread-1012  runnable
1586  simple-error-spawn-thread-910  runnable
1801  process reaper  runnable
1666  process reaper  blocked
395  scala-execution-context-global-395  waiting
1203  simple-output-spawn-thread-721  runnable
...

我从线程内部调用代码段,未来的执行上下文是 global。启动的进程是 JVM 进程,最大允许内存大小为 20G,docker 容器为 480G。因为我保证不会同时调用这个代码段超过 20 次,所以我应该在任何时候都有 80G 的空闲时间,但这显然不是这种情况。

如何确保已启动的进程真正关闭包括所有相关内存?

解决方法

我能够通过更改来减少线程数量

val process = preped.run(true)

val process = preped.run(new ProcessIO(_.close(),_.close(),_.close()))

我现在只有 178 个线程,而且没有进一步增加。不过还是大得惊人。

任何解决/解释这么多线程的答案都将被接受,而不是这个