代码之家  ›  专栏  ›  技术社区  ›  Kaleb Pederson

process.waitfor()、线程和输入流

  •  31
  • Kaleb Pederson  · 技术社区  · 16 年前

    在伪代码中,我要做的是:

    Process proc = runtime.exec(command);
    processOutputStreamInThread(proc.getInputStream());
    processOutputStreamInThread(proc.getErrorStream());
    proc.waitFor()
    

    然而,有时 processOutputStreamInThread 没有看到任何输出,有时会看到。大致上,该方法创建一个 BufferedInputStream 命令的输出并将其发送到记录器。

    根据我看到的情况,我猜 command 不需要把它的所有输出倾倒到 getInputStream() getErrorStream() 从而允许流为空。

    我的试验结果如下:

    (1) waitFor() 在里面 java.lang.Process 是否要求已执行程序的输出在返回前已被读取?

    文件仅说明:

    使当前线程在必要时等待,直到由此表示的进程 Process 对象已终止。如果子进程已终止,则此方法立即返回。如果子进程尚未终止,则调用线程将被阻塞,直到子进程退出。

    (二) 在什么条件下 getInputStream getErrorStream 需要关闭和/或自动关闭?

    文件仅说明:

    获取子进程的错误流。流从该进程对象表示的进程的错误输出流获取管道数据。

    实现说明:最好对输入流进行缓冲。

    user reports 他不得不自己关闭流,但我得到了一个例外,至少有一部分时间表明当我试图关闭流时流已经关闭。

    编辑: 改变 getOutputStream 获取输入流 ,现在出现在上面。

    分辨率: 最后的问题是,在某些情况下,用于处理输出流的线程在非常短的进程完成之后才会运行,从而导致输入流没有给我任何数据。 waitFor 没有等待已执行程序的输出。相反,程序在收集任何输出之前运行并终止。

    我使用线程是因为我不确定在标准错误和标准输出上会得到多少输出,我希望能够同时处理这两个输出,而不阻塞其中一个或另一个,只要其中一个有可用的数据。但是,因为我的线程不能一致地读取执行程序的输出,所以这是一个非解决方案。

    我最后的代码是这样的:

    ProcessBuilder pb = new ProcessBuilder(cmdargs);
    pb.redirectErrorStream(true);
    Process proc = pb.start();
    processOutputStream(proc.getInputStream());
    proc.waitFor()
    
    2 回复  |  直到 15 年前
        1
  •  27
  •   Alexander Pogrebnyak    16 年前

    如果外部进程期望 stdin ,您必须关闭 getOutputStream . 否则你会的 waitFor 永远。

    这里是 When Runtime.exec() won't article 来自javaworld,它描述了exec方法的不同缺陷以及如何避免它们。

    根据我的经验,最好消耗stdout和stderr的子进程(直到它们结束),然后阻塞 等待 . 希望在这一点上你不用等太久。

    卡莱布问题的答案。 然而,在正常情况下,你不应该关闭溪流,因为你 waitingFor 无论什么原因它没有超时,如果您在输出中遇到一些错误条件,并且不想进一步处理子进程的输出,那么您可能需要关闭这些流。然而,当子程序的stdout或stderr管道在另一端关闭时,它是否会终止(崩溃),完全取决于该子程序的实现。不过,大多数shell程序都会在这种情况下终止。

    我真的希望 等待 但是有一些有意义的超时 Process 当你决定放弃对它的监控时,有一个文档化的清理它资源的方法。

        2
  •  2
  •   user257111    16 年前

    我认为这有点违反直觉,但是:

    GetOutputStream获取输出 子进程流。输出到 流通过管道输送到标准中。 进程的输入流 由这个进程对象表示。 实施说明:这是个好主意 用于缓冲输出流。 返回:连接的输出流 到子进程的正常输入。

    我从主进程读取这个输出流,并将其附加到子进程的标准输入,因此当您写入getOutputstream().write()时,实际上是在stdin上写入。

    是否可能要使用.getinputstream()?

    返回: 连接到子进程正常输出的输入流。

    至于process.waitfor(),api文档会说:

    使当前线程等待,如果 必要的,直到过程 由该进程对象表示的 结束。此方法返回 如果子进程 已终止。如果子流程 尚未终止,呼叫 线程将被阻塞,直到 子进程退出。

    我想说,这个被调用的线程将被阻塞,直到进程完成执行为止-您可能仍然在这个阶段处理输出,这取决于其他线程,或者它们可能在线程返回之前已经完成。