2

我启动了一个通过 SyncPipe Runnable 输出到 System.out 的 cmd 应用程序:

public class SyncPipe implements Runnable {

    private final InputStream is;
    private final OutputStream os;

    public SyncPipe(InputStream is, OutputStream os) {
        this.is = is;
        this.os = os;
    }

    public void run() {
        try {
            final byte[] buffer = new byte[1024];
            for ( int length = 0; ( length = is.read(buffer) ) != -1; )
                os.write(buffer, 0, length);
            System.out.print("stopped");
        } catch ( Exception ex ) { 
            ex.printStackTrace(); 
        }
    }

}

我开始 RunItcmd = "C:/bin/read.exe -f D:/test.jpg"

private class RunIt implements Runnable {

    public int p;
    public String cmd;

    public RunIt (int p, String cmd) {
        this.p = p;
        this.cmd = cmd;
    }

    public void run() {
        ProcessBuilder pb = new ProcessBuilder("cmd");
        try {
            process = pb.start();
            (new Thread(new SyncPipe(process.getErrorStream(), System.err))).start();
            (new Thread(new SyncPipe(process.getInputStream(), System.out))).start();
            OutputStream out = process.getOutputStream();
            out.write((cmd + "\r\n").getBytes());
            out.flush();
            out.close();

            try {
                process.waitFor();
            } catch ( InterruptedException e ) {
                e.printStackTrace();
            }

            println("Stopped using %d.", p);
        } catch ( IOException ex ) {
            ex.printStackTrace();
        }
    }

}

我现在的问题是:我怎样才能(new Thread(new SyncPipe(process.getErrorStream(), System.err)))死?给 SyncPipe 一个布尔变量stop,在运行时设置它true,并通过检查它for ( int length = 0; ( length = is.read(buffer) ) != -1 && !stop; )并没有成功。

提前非常感谢。


我最终完成了@Gray 建议的解决方法。它现在有效:

public void run() {
    try {
        final byte[] buffer = new byte[1024];
        do
            if ( is.available() > 0 ) {
                int length = is.read(buffer);
                if ( length != -1 )
                    os.write(buffer, 0, length);
                else
                    stop = true;
            }
        while ( !stop );
    } catch ( Exception ex ) { 
        ex.printStackTrace(); 
    }
}
4

3 回答 3

1

InputStream#read()状态

此方法会一直阻塞,直到输入数据可用、检测到流结束或引发异常。

所以当你进入你的for循环

for ( int length = 0; ( length = is.read(buffer) ) != -1; )
    os.write(buffer, 0, length);

直到到达流的末尾,它才能退出,即。该过程停止或您自己关闭流。

如果整个目的SyncPipe是将内容传递给您的标准输出/错误流,您为什么要停止Thread运行它?

于 2013-10-09T19:15:16.767 回答
1

我现在的问题是:我怎样才能让 (new Thread(new SyncPipe(process.getErrorStream(), System.err))) 死掉?

我相信你将不得不从它下面关闭输入流。我怀疑它在读取中被阻塞,并且没有stop变量设置(即使正确volatile)将使读取线程解除阻塞。

您将需要执行以下操作:

 InputStream is = process.getInputStream();
 InputStream es = process.getErrorStream();
 ...
 is.close();
 es.close();

代码大致如下所示。我不确定您的waitFor()电话是否正在返回。

 InputStream is = process.getInputStream();
 InputStream es = process.getErrorStream();
 (new Thread(new SyncPipe(es, System.err))).start();
 (new Thread(new SyncPipe(is, System.out))).start();
 try {
     OutputStream out = process.getOutputStream();
     out.write((cmd + "\r\n").getBytes());
     out.flush();
     out.close();
     try {
         process.waitFor();
     } catch ( InterruptedException e ) {
         e.printStackTrace();
     }
 } finally {
     is.close();
     es.close();
 }

另一个答案可能是使用该available()方法,InputStream以便您可以循环并检查您的stop标志。看到这个答案:https ://stackoverflow.com/a/1089079/179850

于 2013-10-09T19:15:05.090 回答
1

当底层进程退出时,线程将读取 EOS 并退出。你不必自己做任何特别的事情。

编辑在我看来,从阅读您的评论到其他答案,您的真正问题正在结束该过程。一旦发生这种情况,这些线程就会解开。你正在攻击问题的错误结局。

于 2013-10-09T21:18:49.910 回答