gpt4 book ai didi

java - 异步运行进程并从 stdout 和 stderr 读取

转载 作者:搜寻专家 更新时间:2023-10-30 21:12:22 26 4
gpt4 key购买 nike

我有一些代码运行一个进程并异步读取标准输出和标准错误,然后在进程完成时进行处理。它看起来像这样:

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();

我的问题是我使用 3 个线程来实现这个异步的“运行并获取输出”任务 - 我不知道为什么,但我觉得使用 3 个线程感觉不对。我可以从线程池中分配线程,但这仍然会阻塞这些线程。

有什么我可以做的,也许是使用 NIO,将其减少到更少(1 个?)线程?我能想到的任何事情都会不断地旋转一个线程(除非我添加一些 sleep ),我也不想这样做......

注意:我确实需要边读边读(而不是在进程停止时),而且我确实需要将标准输入与标准错误分开,因此无法进行重定向。

最佳答案

由于您已指定需要随时读取输出,因此没有非多线程解决方案。

不过,您可以将线程数减少到主线程之外的一个:

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

如果你真的不需要在进程结束之前处理错误/输出,你可以稍微简化一下,只使用你的主线程,如下所示:

    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();
}

如果您从正在调用的进程中生成大量输出,这可能不是一个好主意,因为它可能会耗尽磁盘空间……但它可能会稍微快一些,因为它不必旋转上另一个线程。

关于java - 异步运行进程并从 stdout 和 stderr 读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25086150/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com