Apache Commons Exec ライブラリを使用して、外部コマンド ライン アプリケーションを使用する必要がある Java アプリケーションを作成しています。実行する必要があるアプリケーションの読み込み時間がかなり長いため、毎回新しいプロセスを作成するのではなく、1 つのインスタンスを維持することが望ましいでしょう。アプリケーションの仕組みは非常にシンプルです。開始すると、新しい入力を待機し、出力としてデータを生成します。どちらもアプリケーションの標準 I/O を使用します。
つまり、CommandLine を実行してから、PumpStreamHandler を 3 つの別個のストリーム (出力、エラー、および入力) で使用し、それらのストリームを使用してアプリケーションと対話するという考えになります。これまでのところ、1 つの入力と 1 つの出力があり、その後アプリケーションがシャットダウンするという基本的なシナリオでこの作業を行いました。しかし、2 番目のトランザクションを実行しようとするとすぐに、問題が発生します。
CommandLine を作成した後、Executor を作成し、次のように起動します。
this.executor = new DefaultExecutor();
PipedOutputStream stdout = new PipedOutputStream();
PipedOutputStream stderr = new PipedOutputStream();
PipedInputStream stdin = new PipedInputStream();
PumpStreamHandler streamHandler = new PumpStreamHandler(stdout, stderr, stdin);
this.executor.setStreamHandler(streamHandler);
this.processOutput = new BufferedInputStream(new PipedInputStream(stdout));
this.processError = new BufferedInputStream(new PipedInputStream(stderr));
this.processInput = new BufferedOutputStream(new PipedOutputStream(stdin));
this.resultHandler = new DefaultExecuteResultHandler();
this.executor.execute(cmdLine, resultHandler);
次に、3 つの異なるスレッドを起動し、それぞれが異なるストリームを処理します。入力と出力を処理する 3 つの SynchronousQueues もあります (1 つは入力ストリームの入力として使用され、1 つは新しいコマンドが起動されたことを outputQueue に通知するため、もう 1 つは出力用です)。たとえば、入力ストリーム スレッドは次のようになります。
while (!killThreads) {
String input = inputQueue.take();
processInput.write(input.getBytes());
processInput.flush();
IOQueue.put(input);
}
while ループを削除してこれを 1 回だけ実行すると、すべてが完全に機能するように見えます。明らかに、もう一度実行しようとすると、PumpStreamHandler は 2 つの異なるスレッドからアクセスされているため、例外をスローします。
ここでの問題は、スレッドが終了するまで processInput が真にフラッシュされないように見えることです。デバッグ時に、コマンド ライン アプリケーションは、スレッドが終了して初めて実際に入力を受け取りますが、while ループが保持されている場合は入力を受け取りません。processInput をフラッシュするためにさまざまなことを試しましたが、何も機能していないようです。
誰かが以前に似たようなことを試みたことがありますか? 不足しているものはありますか?どんな助けでも大歓迎です!