我正在编写一个 Java 应用程序,需要使用 Apache Commons Exec 库的外部命令行应用程序。我需要运行的应用程序具有相当长的加载时间,因此最好保持一个实例处于活动状态,而不是每次都创建一个新进程。该应用程序的工作方式非常简单。一旦启动,它就会等待一些新的输入并生成一些数据作为输出,这两者都使用应用程序的标准 I/O。
因此,我们的想法是执行 CommandLine,然后将 PumpStreamHandler 与三个单独的流(输出、错误和输入)结合使用,并使用这些流与应用程序交互。到目前为止,我已经在基本场景中完成了这项工作,其中我有一个输入,一个输出,然后应用程序关闭。但当我尝试进行第二笔交易时,就出了问题。
创建 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);
然后,我继续启动三个不同的线程,每个线程处理不同的流。我还有三个同步队列来处理输入和输出(一个用作输入流的输入,一个用于通知输出队列已启动新命令,另一个用于输出)。例如,输入流线程如下所示:
while (!killThreads) {
String input = inputQueue.take();
processInput.write(input.getBytes());
processInput.flush();
IOQueue.put(input);
}
如果我删除 while 循环并只执行一次,一切似乎都会完美运行。显然,如果我尝试再次执行它,PumpStreamHandler 会抛出异常,因为它已被两个不同的线程访问。
这里的问题是,在线程结束之前,processInput 似乎并未真正刷新。调试时,命令行应用程序仅在线程结束后才真正接收其输入,但如果保留 while 循环,则永远不会获取它。我尝试了很多不同的方法来刷新 processInput,但似乎没有任何效果。
以前有人尝试过类似的事情吗?我有什么遗漏的吗?任何帮助将不胜感激!