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

}

私はRunItを開始しますcmd = "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

私の質問: どうすれば (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()メソッド onを使用して、ループしてフラグInputStreamを確認できるようにすることです。stopこの回答を参照してください: https://stackoverflow.com/a/1089079/179850

于 2013-10-09T19:15:05.090 に答える
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

基になるプロセスが終了すると、スレッドは EOS を読み取り、終了します。自分で特別なことをする必要はありません。

編集あなたのコメントを他の回答に読んだところ、あなたの本当の問題はプロセスを終了しているように思えます。これらのスレッドは、それが発生するとすぐに解消されます。あなたは問題の間違った終わりを攻撃しています。

于 2013-10-09T21:18:49.910 に答える