1

我有一个将 WAV 顺序转换为 MP3 的批处理过程。问题是在几千个文件之后打开的文件太多,并且超出了文件限制。

它这样做的原因是因为 SystemCommandTasklet 中的代码:

FutureTask<Integer> systemCommandTask = new FutureTask<Integer>(new Callable<Integer>() {
    public Integer call() throws Exception {
        Process process = Runtime.getRuntime().exec(command, environmentParams, workingDirectory);
        return process.waitFor();
    }
});

这有一个令人讨厌的副作用,就是让我依赖 JVM 来清理进程,让文件保持打开状态等等。

我把它改写成这样:

FutureTask<Integer> systemCommandTask = new FutureTask<Integer>(new Callable<Integer>() {
    public Integer call() throws Exception {
        Process process = Runtime.getRuntime().exec(command, environmentParams, workingDirectory);
        int status = process.waitFor();

        process.getErrorStream().close();

        process.getInputStream().close();

        process.getOutputStream().flush();
        process.getOutputStream().close();

        process.destroy();

        return status;
    }

});

我有 95% 的把握这在我的 mac 上有效(感谢 lsof),但是我如何进行适当的测试以在任何系统上工作以证明我正在尝试做的事情确实有效?

4

3 回答 3

1
  1. 您不应为此使用 Runtime#exec(),因为该进程未附加到 JVM。请查看 jlProcessBuilder ,它返回一个由 JVM 进程控制的进程。因此转储进程可能会迫使系统释放/关闭资源。
  2. 您还应该使用 jucExecutors 来安排和限制进程。
  3. 您也可以使用“ulimit -Sn”读取限制(由于系统健康,不应首选“ulimit -Hn”;)。
  4. 检查转换媒体的工具是否在完成后保留资源(泄漏、等待呼叫者信号等)。
于 2010-08-27T20:15:31.967 回答
0

您可以尝试编写代码来避免它。

你为什么不主动限制一次任务的数量,比如 100?

在这种情况下,您可以使用一些池机制来执行您的工作,例如线程池。

于 2010-08-27T19:19:07.903 回答
0

证明将是困难的。但 ...

创建一个(虚拟)命令,它不会做太多但会锁定文件,就像真实的东西一样。这可以确保您的测试不依赖于实际使用的命令。

创建一个启动 SystemCommandTask 的测试,使用旧版本,但使用 DummyCommand。让它经常启动任务,直到你得到预期的异常。让我们调用所需的任务数 N

更改测试以启动 100xN 任务。

将任务更改为新版本。如果测试变为绿色,您应该有理由确定您的代码可以正常工作。

于 2010-08-27T19:38:34.190 回答