7

a を使用しProcessBuilderてプロセスを実行します。入力/出力ストリームを処理するには、スレッド プール ( ) でそれらを処理する対応するランナブルを送信しますExecutors.newCachedThreadPool()
私は結果を得ますが、時々何も得られません。
たとえばcmd \C dir、プロセスビルダーに対してdirback の結果を取得しますが、何も取得しない場合があります (結果が を処理する実行可能ファイルから返されるように見えるにもかかわらずprocess.getInputStream)。
どうすればこれをデバッグできますか? 断続的に現れます。同じコードを使用した場合、問題はありませんでしたnew Thread(runnable).start()。スレッドプールに切り替えた後、発生し始めました。

更新:
何かを見つけたと思います:
で次のことを行いますRunnable:

 try {  
    while ( (line = br.readLine()) != null) {  
            pw.println(line);  
                sb.append(line);   
    }  
    System.out.println("Finished reading "+sb.length());  
} catch (IOException e) {             
    e.printStackTrace();  
}  
finally{  
   pw.flush();     
  try{
    isr.close();  
  }catch(Exception e){}  
}

うまくいかない場合は、 を出力しFinished reading 521ます。しかし、私はpwand notを介して結果を取得しようとしていsbます。
pwランナブルで渡す PrintWriter pw = PrintWriter(outputStream);` です

更新 2: 次
の ようです:入力ストリームを処理した実行可能ファイルが終了する前にstatus = process.waitFor();、より早く戻ります。これはどのように起こりますか? javadoc: を読みました。つまり、I/O ストリームを消費する 前に戻ることができるということですか?

the calling thread will be blocked until the subprocess exits

更新 3: Ruby でも
同じ問題のようです。つまり、プロセスの終了と出力の消費の間に競合状態があります。

4

1 に答える 1

1

はい。プロセス間の stdio はバッファリングされます (通常は 4KB バッファ)。処理 バッファに書き込み、存在します。プロセス B には 2 つのスレッドがあります。1 つは A の終了を待ち、もう 1 つは A からの出力を読み取ります。どのスレッドが最初に実行されるかを確認する方法はありません。

process.waitFor();そのため、バッファリングされたすべての出力が読み取られる前に返される可能性があります (多くの出力がある場合でも可能性があります) 。

フラッシュは、A がすべてを書き込んだことを確認するだけなので、ここでは役に立たないことに注意してください。同様の方法で B にデータを「強制的に」読み取る方法はありません。

したがって、終了ステータスを覚えておき、入力ストリームから EOF を読み取った場合にのみ、プロセスが「完全に終了した」と見なす必要があります。

編集1 つの解決策は、 をストリーム ゴブラーに移動waitFor()し、ゴブラーを に変換してCallableからエグゼキューターに送信し、FutureAPI ( example ) を使用して結果を取得することです。

于 2013-03-11T10:21:32.753 に答える