我发现所有关于从 Process
stdout 读取的讨论都是以阻塞方式进行的,如下所示:
Process process=Runtime.getRuntime().exec(cmd);
BufferedReader in=new BufferedReader(
new InputStreamReader(process.getInputStream()));
for(String line;(line=in.readLine())!=null;)
{
useText(line);
}
如果我试图避免阻塞,我的选择是使用 in.ready()
轮询流。
但我真正需要的是让进程继续运行并做一些有用的事情,并且只在数据实际可用时才尝试读取任何内容。所以我正在寻找类似 Qt 的 QProcess::readyReadStandardOutput
信号的东西。请注意,BufferedReader
的方法ready
不是我要找的:它只是一种我必须反复检查的方法,而不是任何类型的信号。
Java 中有类似的东西吗?
最佳答案
如果你有一个事件循环,你可以启动一个后台线程来向那个事件循环添加事件。
例如
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectErrorStream(true); // capture errors as well.
Process process = pb.start();
BufferedReader in = new BufferedReader(
new InputStreamReader(process.getInputStream()));
Thread t = new Thread(() -> {
try {
for (String line; (line = in.readLine()) != null; ) {
Activity.runOnUiThread(() -> useText(line));
}
} catch (Exception e) {
logger.log(e);
} finally {
Activity.runOnUiThread(() -> noMoreText());
}
});
t.setDaemon(true);
t.start();
你可以有一个线程只执行 queue.add(in.readLine())
然后你的主线程可以轮询这个队列。这样所有多线程问题都变得简单且包含在内。
static final String EOF = new String(); // use for == comparison later
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectErrorStream(true); // capture errors as well.
Process process = pb.start();
BufferedReader in = new BufferedReader(
new InputStreamReader(process.getInputStream()));
int capacity = 1024;
BlockingQueue<String> lines = new ArrayBlockingQueue<>(capacity);
Thread t = new Thread(() -> {
try {
for (String line; (line = in.readLine()) != null; ) {
lines.add(line);
while (lines.remainingCapacity() < 2) // don't run out of memory if too much.
Thread.sleep(50);
}
} catch (Exception e) {
logger.log(e);
} finally {
lines.offer(EOF);
}
});
t.setDaemon(true);
t.start();
// later in a loop
String line = lines.poll();
if (line == null) // no data yet.
else if (line == EOF) // we have the EOF marker.
关于java - 我怎样才能在 stdout/stderr 准备就绪时进行回调而不是忙于轮询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53113901/