VBScriptへの呼び出しをいくつか使用して外部データを取得することはできません。私はクロスプラットフォームの柔軟性を失うので、この実装は本当に嫌いですが、少なくとも問題を緩和するために、同様の* nixスクリプトを開発する可能性があります。誰かが尋ねる前に、ははデータを収集するために外部スクリプトを呼び出す必要がありません。私はその原因で生きるだろう。Java - 複数の同時実行時の問題runtime.exec()InputStreams
exec()
のプロセスは、Runnable
に拡張されたカスタムクラスで実行されます。これはBufferedReader
を使用してgetInputStream()
のデータを読み込みます。
編集:要求としてより多くのコードを追加しましたが、私は余分なコードが関連している方法を見ていない:)それはフォーマットするしばらく時間がかかったので、私は、それが役に立てば幸い!それは醜いだが、建設的な批判が奨励されている場合、私は、個々のコマンドを実行するとああ、と私は期待して私がデータを収集し、...私のコードのスタイルに
public class X extends JFrame implements Runnable {
...
static final int THREADS_MAX = 4;
ExecutorService exec;
...
public static void main(String[] args) {
...
SwingUtilities.invokeLater(new X("X"));
} // End main(String[])
public X (String title) {
...
exec = Executors.newFixedThreadPool(THREADS_MAX);
...
// Create all needed instances of Y
for (int i = 0; i < objects.length; i++) {
Y[i] = new Y(i);
} // End for(i)
// Initialization moved here for easy single-thread testing
// Undesired, of course
for (int i = 0; i < objects.length; i++) {
Y[i].initialize(parent);
} // End for(i)
} // End X
class Y implements Runnable {
// Define variables/arrays used to capture data here
String computerName = "";
...
public Y(int rowIndex) {
row = rowIndex;
...
computerName = (String)JTable.getValueAt(row, 0);
...
exec.execute(this);
} // End Y(int)
public void run() {
// Initialize variables/arrays used to capture data here
...
// Initialization should be done here for proper threading
//initialize(parent);
} // End run()
public void initialize(Z obj) {
runTime = Runtime.getRuntime();
...
try {
process = runTime.exec("cscript.exe query.vbs " + computerName);
stdErr = process.getErrorStream();
stdIn = process.getInputStream();
isrErr = new InputStreamReader(stdErr);
isrIn = new InputStreamReader(stdIn);
brErr = new BufferedReader(isrErr);
brIn = new BufferedReader(isrIn);
while ((line = brIn.readLine()) != null) {
// Capture, parse, and store data here
...
} // End while
} catch (IOException e) {
System.out.println("Unable to run script");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
stdErr.close();
stdIn. close();
isrErr.close();
isrIn. close();
brErr. close();
brIn. close();
} catch (IOException e) {
System.out.println("Unable to close streams.");
} // End try
} // End try
} // End initialize(Z)
...
} // End class Y
} // End class X
を簡単に行きます。しかし、クラスのrun()
ブロック内のコマンドを実行すると(呼び出しが並行していることを意味します)、入力ストリームが1つだけ生成されたように見えますが、すべてBufferedReaders
が同時に消費されます。
問題をデバッグするために、私は、入力ストリームを読み込んでいたクラスのインスタンスが前に付いたコンソールで、各消費された行を出力します。私は、彼らがからインスタンスとインスタンスのための外にあってもよいことを理解、以下のようなものを期待していますが、単一インスタンスの行の順序はそのまま次のようになります。
exec 0: Line1
exec 1: Line1
exec 2: Line1
exec 0: Line2
exec 1: Line2
exec 2: Line2
exec 0: Line3
exec 1: Line3
exec 2: Line3
...
奇妙だ私は何の期待数を取得されます出力の最初の行(Microsoft (R) Windows Script Host Version 5.7
)のインスタンスですが、この行の後に入力ストリームにデータを生成するプロセスは1つだけで、次の例のようにすべてのリーダーがこの1つのストリームを無作為に消費します。
exec 2: Microsoft (R) Windows Script Host Version 5.7
exec 0: Microsoft (R) Windows Script Host Version 5.7
exec 1: Microsoft (R) Windows Script Host Version 5.7
exec 0: line2
exec 1: line3
exec 2: line4
...
さらに悪いことに、読者のストールとreadLine()
は決してnullを返しません。私は、このタイプの振る舞いはバッファサイズと関係があるかもしれないと読んでいますが、短い出力でも2つの並行スレッドしか実行しない場合でも、同じ動作を示します。 stdErr
には何も記録されておらず、問題があることを示しています。
これがスクリプトホストの制限事項であるかどうかを確認するために、START
複数のスクリプトインスタンスを同時に実行するバッチファイルを作成しました。 これは、cmdシェルでがJavaの以外で実行されたことを示す必要があり、いくつかの独自のシェルを起動します。しかし、各同時実行インスタンスは、期待される結果を完全に返し、うまく動作しました。
編集:別のトラブルシューティングのアイデアとして、私は再度有効に同時実行することにしましたが、私のY.run()
ブロックに次のように挿入して、私の初期化メソッドをずらす:私のコードに
try {
Thread.sleep((int)(Math.random() * 1200));
} catch (InterruptedException e) {
System.out.println("Can't sleep!");
} // End try
initialize(monitor);
。最初の数行は複数の出力を見始めるが、同じプロデューサを消費する複数の消費者にすばやく戻って、最初の完了したストリームが閉じられるとすぐに残りのコンシューマが例外を発生させる。次の消費者はIOException: Read error
を発射し、残りはIOException: Stream closed
を発射する!
はmaaartinusによると、今の質問は望ましくない動作の原因になっているものになり、複数の実行に並行InputStreams
ことは可能ですか?どのようにして独立して入力ストリームを取得できますか?私はそれを避けることができれば、データを処理するために一時ファイルに書き込む必要はありません。
'だから私は混乱している - ?複数の入力を処理することが可能なJavaは、同時にか流れている'確かに、それはあります。 Windows Script Hostに何か問題がある可能性があります。私は簡単なスクリプト(または別のプログラム)を試して、簡単な出力を得ようとしています。 – maaartinus
いくつかのフィールドが静的であるように聞こえるのは間違いです。もっとクラスを投稿できますか? –
'さらに悪いことに、読者が失速とのreadLine()プロセス当たり、すなわち、二つのスレッド、各ストリームに自身のスレッドを使用してみてくださいnull.'返すことはありません。各ストリームに小さなバッファがあり、プロセスがいっぱいになるとブロックされます(もう一方のストリームから何も得られません)。 – maaartinus