wmic command executed in Java blocked

1950 ワード

Javaが次のwindowsのwmicコマンドを実行すると、
wmic cpu get loadpercentage /value
wmic os get totalvisiblememorysize,freephysicalmemory /value
wmic process where(name="java.exe") get name,creationdate,workingsetsize,pagefileusage /value

ProcessのInputStreamから実行結果を読み出すと、次のコードで示すように、プログラムが読み出された文にブロックされます.
 
ProcessBuilder pb = new ProcessBuilder("wmic",...);  
// pb.redirectErrorStream(true);   //     1
Process p = pb.start(); 
// p.getOutputStream().close();    //     2
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));  
String tmp = null;  
  
while ((tmp = br.readline()) != null) {    //     
    System.out.println(tmp);  
}  
int exitValue = p.waitfor();

Google,Java method calls the WMIC commandによると,オペレーティングシステムによっては各プロセスのInputStreamの大きさが等しくなく,InputStreamが実行結果を保存するのに十分なスペースがない場合,実行結果がErrorStreamに出力されるという.しかし、上記のアノテーションコード1を解放すると(もう1つのスキームは、InputStreamから実行結果を読み出し、ErrorStreamから実行結果を読み出す2つのスレッドを作成すること)、プログラムはreadコードにブロックされます.
Googleに続き、Processは入力終了待ちのフラグである可能性があると述べ、上のコードではwmicコマンドを入力しただけですが、入力を終了していないので、上のコメントコード2を放して問題解決します.やっと正しい出力が得られるようになりました.
なお、作成したProcessで個別のcmdウィンドウを開き、上記のwmicコマンドを実行すると、正確な出力結果が得られます.
 
上記のコードはWin 7,Win 2008上でよく同時実行できる.しかし、WinXPとWin 2003の同時実行では、次のようなエラーが発生しました.
Win32 Error: The process cannot access the file because it is being used by another process

 WinXPとWin 2003でコードを実行すると、一時的なTempWmicBatchFile.batファイルが生成されることが観察されたので、一時的なファイルへのアクセスが同期されていないため、上記の現象を説明することができます.しかし、各コマンドの実行に対してこの一時ファイルを同期すると、コマンドが多い場合に、待ち時間の大きいリクエストが発生する可能性があります.常に最新のデータを取得する必要がないことを考慮して、各コマンドの実行結果をキャッシュし、コマンドの実行を同期します.これにより、来るたびに新しいコマンドはキャッシュの実行結果を取得し、コマンドキューに自分を置くことができます.これにより、上記のエラーを効果的に回避できます.