我想从Java启动一个进程,读取它的输出,并获取它的返回代码.但是当它正在执行时,我希望能够取消它.我首先启动这个过程:
ProcessBuilder pb = new ProcessBuilder(args); pb.redirectErrorStream(true); Process proc = pb.start();
如果我调用proc.waitFor(),在进程退出之前我什么也做不了.所以我假设我需要这样的东西:
while (true) { see if process has exited capture some output from the process decide if I want to cancel it, and if so, cancel it sleep for a while }
这是正确的吗?有人能给我一个如何在Java中做到这一点的例子吗?
这是我认为你想做的一个例子:
ProcessBuilder pb = new ProcessBuilder(args); pb.redirectErrorStream(true); Process proc = pb.start(); InputStream is = proc.getInputStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); String line; int exit = -1; while ((line = br.readLine()) != null) { // Outputs your process execution System.out.println(line); try { exit = proc.exitValue(); if (exit == 0) { // Process finished } } catch (IllegalThreadStateException t) { // The process has not yet finished. // Should we stop it? if (processMustStop()) // processMustStop can return true // after time out, for example. proc.destroy(); } }
你可以改进它:-)我现在没有真正的环境来测试它,但你可以在这里找到更多的信息.
我建议检查Apache Commons Exec以避免重新创建轮子.它具有一些很好的功能,如在同步和异步执行之间进行选择,以及产生监视程序进程的标准解决方案,可以帮助在执行过程中超时执行.
像这样的助手类可以解决这个问题:
public class ProcessWatcher implements Runnable { private Process p; private volatile boolean finished = false; public ProcessWatcher(Process p) { this.p = p; new Thread(this).start(); } public boolean isFinished() { return finished; } public void run() { try { p.waitFor(); } catch (Exception e) {} finished = true; } }
然后,您将完全按照您的描述实现您的循环:
Process p = Runtime.getRuntime().exec("whatever command"); ProcessWatcher pw = new ProcessWatcher(p); InputStream output = p.getInputStream(); while(!pw.isFinished()) { processOutput(output); if(shouldCancel()) p.destroy(); Thread.sleep(500); }
根据您希望破坏进程的条件,您可能希望在单独的线程中执行此操作.否则,您可能会在等待处理更多程序输出时阻塞,并且永远不会真正获得销毁它的选项.
编辑:McDowell在下面的评论中100%正确,所以我已经完成变量volatile.