Java Process.waitFor()和IO流

时间:2012-11-13 10:49:26

标签: java runtime subprocess stdio

我有以下代码;

String[] cmd = { "bash", "-c", "~/path/to/script.sh" };
Process p = Runtime.getRuntime().exec(cmd);

PipeThread a = new PipeThread(p.getInputStream(), System.out);
PipeThread b = new PipeThread(p.getErrorStream(), System.err);

p.waitFor();

a.die();
b.die();

PipeThread类非常简单,所以我将其全部包含在内;

public class PipeThread implements Runnable {

    private BufferedInputStream in;
    private BufferedOutputStream out;

    public Thread thread;

    private boolean die = false;

    public PipeThread(InputStream i, OutputStream o) {
        in = new BufferedInputStream(i);
        out = new BufferedOutputStream(o);
        thread = new Thread(this);
        thread.start();
    }

    public void die() { die = true; }

    public void run() {
        try {
            byte[] b = new byte[1024];
            while(!die) {
                int x = in.read(b, 0, 1024);
                if(x > 0) out.write(b, 0, x);
                else die();
                out.flush();
            }
        }
        catch(Exception e) { e.printStackTrace(); }

        try { 
            in.close();
            out.close();
        }
        catch(Exception e) { }
    }
}

我的问题是这个;即使在子进程终止后,p.waitFor()也会无休止地阻塞。如果我创建一对PipeThread个实例,那么p.waitFor()就能完美运行。 io流的管道是什么导致p.waitFor()继续阻塞?

我很困惑,因为我认为IO流是被动的,无法保持进程存活,或者让Java认为进程仍然存在。

2 个答案:

答案 0 :(得分:0)

在您的PipeThread代码中,您将永远循环直到!die - 但是在PipeThread.die()之后调用p.waitFor() - 究竟是什么阻止了PipeThread个帖子?

答案 1 :(得分:0)

因此,经过多次头疼,我意识到发生了什么。 p.waitFor()实际上不是无限期地阻止,而是我检查它的方法失败了; System.out.println()之后的p.waitFor()语句。

PipeThread是我在之前的项目中所处的类,我经常使用它在一个单独的线程中将一个流传输到另一个流。

这必须是我第一次将其与System.out一起使用。 PipeThread会在阅读EOF时关闭传递的所有流。在这种情况下,两个流都包含我的标准输出,因此使用System.out.println进行调试变得不可能...... :(

奇怪的是,IOException没有抛出System.out.println(),我会调查。