当前位置:  开发笔记 > 编程语言 > 正文

从Java运行外部程序,读取输出,允许中断

如何解决《从Java运行外部程序,读取输出,允许中断》经验,为你挑选了3个好方法。

我想从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中做到这一点的例子吗?



1> Paulo Guedes..:

这是我认为你想做的一个例子:

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();
    }
}

你可以改进它:-)我现在没有真正的环境来测试它,但你可以在这里找到更多的信息.


如果一段时间内没有输出怎么办?在有准备好阅读的行之前,这不会挂在br.readLine()上吗?我不确定我的进程会发送多少输出.
去点.您可以创建一个单独的线程来分析进程是否必须停止.它可以与while循环并行运行,如果它挂起一段时间(或任何其他条件),则会破坏该进程.

2> AWhitford..:

我建议检查Apache Commons Exec以避免重新创建轮子.它具有一些很好的功能,如在同步和异步执行之间进行选择,以及产生监视程序进程的标准解决方案,可以帮助在执行过程中超时执行.



3> Marty Lamb..:

像这样的助手类可以解决这个问题:

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.

推荐阅读
mobiledu2402851373
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有