我已经经历了这么多相关的StackOverflow问题,以至于我迷失了这些问题,而且我已经用多种方式编码,但似乎没有一个方法可以解决这个问题。适用于我:如何在同一时间接收来自同一进程的输入的同时,将输出发送到同一命令并进行多次处理? (有关类似问题,请参阅Input various strings to same process in Java,但结论只有理论上的答案。) 命令(命令行,来自C ++可执行文件)加载一个大文件,然后我想非常快速地向它发送输入,找回答案,在其间做其他事情,然后发送不同的输入并得到相应的答案。将其乘以数千或数百万次。
一个实现,包含线程:
ProcessBuilder pb = new ProcessBuilder(command.split(" "));
kenLMProcess = pb.start();
KenLMInThread lmInput = new KenLMInThread(kenLMProcess.getInputStream());
KenLMInThread lmError = new KenLMInThread(kenLMProcess.getErrorStream());
KenLMOutThread lmOutput = new KenLMOutThread(kenLMProcess.getOutputStream());
lmOutput.inStr = "Test . \n";
lmInput.start();
lmOutput.start();
lmError.start();
lmOutput.join();
lmInput.join();
lmError.join();
outStr = lmInput.newStr;
但是join会一直等到线程结束。如果我不想等到它结束怎么办?我似乎无法弄清楚如何使用wait()来达到这个目的。对于我来说,每次查询命令时,我都不必保持打开和关闭新的输出流和输入流。但至少比每次启动一个新的ProcessBuilder更好。
这里是KenLMOutThread的run():
public void run() {
try {
pw.write(inStr+"\n");
pw.write('\n');
} catch (Exception e) {
System.out.println("Error while inputting to KenLM.");
e.printStackTrace();
} finally {
pw.flush();
try {
pw.flush();
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
据说冲洗应该让它继续前进,并且" \ n"最后应该有所帮助,但它只是挂起,除非我使用close。如果我使用close,我就不能再使用OutputStream了。我也无法从Process创建一个新的OutputStream。
如果有帮助,这里有一个更简单的实现,包含所有内容(取自How to send EOF to a process in Java?): 请注意,使用close(),使用flush()而不使用close()会导致程序挂起。
public static String pipe(String str, String command2) throws IOException, InterruptedException {
Process p2 = Runtime.getRuntime().exec(command2);
OutputStream out = p2.getOutputStream();
out.write(str.getBytes());
out.close();
p2.waitFor();
BufferedReader reader
= new BufferedReader(new InputStreamReader(p2.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
return sb.toString();
}
我尝试过的其他事情:
使用exec():处理kenLMProcess = Runtime.getRuntime()。exec(command);
将命令进程放在自己的线程中:KenLMProcessThread procThread = new KenLMProcessThread(pb.start());
答案 0 :(得分:0)
如果目标进程挂起除非你关闭输出流,那么问题就在于此:它在执行任何操作之前一直读到流结束。在发送端你无能为力。