【问题标题】:How to monitor external process ran by ProcessBuilder?如何监控 ProcessBuilder 运行的外部进程?
【发布时间】:2012-07-16 18:35:14
【问题描述】:

这应该很简单,但我在JavaDocs 中看不到任何帮助。

我需要的是从我的 Java 代码中运行一些外部进程,然后能够监视该进程是否已关闭。换句话说,我希望能够可靠地确定我的外部进程是否未被用户结束。

如果不存在跨平台解决方案,我会接受任何在 Linux 下工作的东西。

我当前的sn-p代码:

public static void main(String[] args) {
    ProcessBuilder pb = new ProcessBuilder("some proces name");

    try {
        Process p = pb.start();
        // p.isRunning(); <- now, that would be helpful :-)
    } catch (IOException e) {
        e.printStackTrace();
    }
}

【问题讨论】:

  • “关闭”与“未由用户结束”是什么意思。您是在谈论错误代码还是其他输出?
  • 好吧,说“由用户结束”可能并不那么准确。我真正想知道的是该进程是否在任何给定时间仍在运行。

标签: java multithreading process


【解决方案1】:

启动一个调用Process.waitFor() 的新线程,并在该调用返回时设置一个标志。然后,您可以随时检查该标志以查看该过程是否已完成。

public class ProcMon implements Runnable {

  private final Process _proc;
  private volatile boolean _complete;

  public boolean isComplete() { return _complete; }

  public void run() {
    _proc.waitFor();
    _complete = true;
  }

  public static ProcMon create(Process proc) {
    ProcMon procMon = new ProcMon(proc);
    Thread t = new Thread(procMon);
    t.start();
    return procMon;
  }
}

(省略了一些样板)。

【讨论】:

    【解决方案2】:

    我不确定我是否理解这个问题,但一种方法是致电process.exitValue();。如果进程尚未终止,则抛出异常:

    /**
     * Returns the exit value for the subprocess.
     *
     * @return  the exit value of the subprocess represented by this 
     *          <code>Process</code> object. by convention, the value 
     *          <code>0</code> indicates normal termination.
     * @exception  IllegalThreadStateException  if the subprocess represented 
     *             by this <code>Process</code> object has not yet terminated.
     */
    abstract public int exitValue();
    

    如果您不介意 hack,如果您在使用 UNIXProcess 类的 ~Unix 系统上工作,则可以执行以下操作。然而,这确实使用了反射:

    ProcessBuilder pb = new ProcessBuilder("/bin/sleep", "5");
    Process process = pb.start();
    // open accessability of the UNIXProcess.hasExited field using reflection
    Field field = process.getClass().getDeclaredField("hasExited");
    field.setAccessible(true);
    // now we can get the field using reflection
    while (!(Boolean) field.get(process)) {
        ...
    }
    

    【讨论】:

    • 想了一下,但这听起来有点像 API '滥用'。我想知道进程是否正在运行,而不是进程终止是否没有发生。我知道它应该是相同的,但老实说,我期待一些 API 组件将采用现有的 Process 实例,并可以提供一些关于该进程中运行的线程状态的额外元数据。
    • @ŁukaszBachman 我根本不会认为这是 API“滥用”。它只是非布尔条件。我还添加了一种获取 hasExited 内部值的方法,但它是一种使用反射的 hack。
    • 我会选择 waitFor(),但 +1 用于反思。
    【解决方案3】:

    根据问题的特定代码 sn-p,我可能会补充一点,因为从 1.8 开始,Process 类有一个 isAlive() 方法可用

    文档链接:https://docs.oracle.com/javase/8/docs/api/java/lang/Process.html

    祝所有阅读本文的人好运!

    【讨论】:

      猜你喜欢
      • 2014-05-08
      • 1970-01-01
      • 2023-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-10
      相关资源
      最近更新 更多