我在linux中为java进程对象调用exitValue()时得到“0”值但偶尔子线程(错误和输出流读取器)没有完成并且卡在连接中。进程的exitValue()的“0”值是否应该保证所有子进程都成功终止?
private class ReadStdoutThread extends Thread {
private Process m_prc;
private StringBuffer m_sb;
public ReadStdoutThread(Process prc, StringBuffer sb) {
m_prc = prc;
m_sb = sb;
}
public void run() {
BufferedReader stdout =
new BufferedReader(new InputStreamReader(m_prc.getInputStream()));
String line = null;
try {
while ((line = stdout.readLine()) != null) {
System.out.println("Stdout: " + line);
m_sb.append(line + "\n");
}
stdout.close();
} catch (IOException e) {
System.out.println(e.toString());
return;
}
}
}
private class ReadStderrThread extends Thread {
private Process m_prc;
private StringBuffer m_sb;
public ReadStderrThread(Process prc, StringBuffer sb) {
m_prc = prc;
m_sb = sb;
}
public void run() {
BufferedReader stderr =
new BufferedReader(new InputStreamReader(m_prc.getErrorStream()));
String line = null;
try {
while ((line = stderr.readLine()) != null) {
System.out.println("Stderr: " + line);
m_sb.append(line + "\n");
}
stderr.close();
} catch (IOException e) {
System.out.println(e.toString());
return;
}
}
}
public static String runCmd(String cmd, long timeoutMS) throws IOException,
InterruptedException {
Process prc = Runtime.getRuntime().exec(cmd);
long startTimeMS = System.currentTimeMillis();
boolean isRunning = true;
System.out.println("Command has started.");
StringBuffer sb = new StringBuffer();
ReadStdoutThread ot = new HostCommand().new ReadStdoutThread(prc, sb);
ReadStderrThread et = new HostCommand().new ReadStderrThread(prc, sb);
ot.start();
et.start();
if (timeoutMS == 0) {
System.out.println("Thread will wait until command is completed.");
prc.waitFor();
} else {
System.out.println("Command timeout (ms): " + timeoutMS);
synchronized (prc) {
int n = -1;
while (isRunning) {
prc.wait(1000);
try {
n = prc.exitValue();
System.out.println("Command has completed with value: " +
n);
m_processExitValue = n;
isRunning = false;
} catch (IllegalThreadStateException e) {
// command is still running
isRunning = true;
}
if ((System.currentTimeMillis() - startTimeMS >
timeoutMS) && isRunning) {
System.out.println("Timeout has reached, and command is still running. Command will be interrupted.");
prc.destroy();
m_processExitValue = n;
isRunning = false;
}
}
}
}
try {
ot.join(timeoutMS);
}
catch(InterruptedException e) {
throw e;
}
try {
et.join(timeoutMS);
}
catch(InterruptedException e) {
throw e;
}
return sb.toString();
}
答案 0 :(得分:0)
根据文档,如果任何子进程尚未终止,该方法应返回IllegalThreadStateException,否则返回0表示正常终止。
来源:https://docs.oracle.com/javase/7/docs/api/java/lang/Process.html
答案 1 :(得分:0)
无法保证ReadStdoutThread和ReadStderrThread已完成执行。 Process waitFor
API与您生成的两个单独的线程之间没有同步,以读取Process的标准输入和错误流。您需要在调用ot.join();et.join();
后使用:ot.start();et.start();
。基本上,应在调用Process.waitFor()
之前调用join