Che*_*tah 12 java multithreading
我有一些代码运行一个进程,并从stdout和stderr异步读取,然后在进程完成时进行处理.它看起来像这样:
Process process = builder.start();
Thread outThread = new Thread(() -> {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
// Read stream here
} catch (Exception e) {
}
});
Thread errThread = new Thread(() -> {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
// Read stream here
} catch (Exception e) {
}
});
outThread.start();
errThread.start();
new Thread(() -> {
int exitCode = -1;
try {
exitCode = process.waitFor();
outThread.join();
errThread.join();
} catch (Exception e) {
}
// Process completed and read all stdout and stderr here
}).start();
Run Code Online (Sandbox Code Playgroud)
我的问题在于我使用3个线程来实现这个异步"run-and-get-output"任务 - 我不知道为什么,但我觉得使用3个线程感觉不对.我可以从线程池中分配线程,但这仍然会阻塞这些线程.
有什么我可以做的,也许是NIO,将这个减少到更少的(1?)线程?我能想到的任何东西都会不断地旋转一个线程(除非我添加几个睡眠),我真的不想这样做......
注意:我确实需要随时阅读(而不是在进程停止时)并且我确实需要将stdin与stderr分开,因此无法进行重定向.
由于您已指定需要随时读取输出,因此没有非多线程解决方案。
不过,您可以将线程数量减少到主线程之外的一个:
Process process = builder.start();
Thread errThread = new Thread(() -> {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
// Read stream here
} catch (Exception e) {
}
});
errThread.start();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
// Read stream here
} catch (Exception e) {
}
// we got an end of file, so there can't be any more input. Now we need to wait for stderr/process exit.
int exitCode = -1;
try {
exitCode = process.waitFor();
errThread.join();
} catch (Exception e) {
}
// Process completed
Run Code Online (Sandbox Code Playgroud)
如果您确实不需要在进程结束之前处理错误/输出,您可以稍微简化一下,只使用主线程,如下所示:
File stderrFile = File.createTempFile("tmpErr", "out");
File stdoutFile = File.createTempFile("tmpStd", "out");
try {
ProcessBuilder builder = new ProcessBuilder("ls /tmp");
Process p = builder.start();
int exitCode = -1;
boolean done = false;
while (!done) {
try {
exitCode = p.waitFor();
done = true;
} catch (InterruptedException ie) {
System.out.println("Interrupted waiting for process to exit.");
}
}
BufferedReader err = new BufferedReader(new FileReader(stderrFile));
BufferedReader in = new BufferedReader(new FileReader(stdoutFile));
....
} finally {
stderrFile.delete();
stdoutFile.delete();
}
Run Code Online (Sandbox Code Playgroud)
如果您从正在调用的进程中生成大量输出,这可能不是一个好主意,因为它可能会耗尽磁盘空间......但它可能会稍微快一些,因为它不必启动另一个线程。