Java Runtime.exec().waitFor()实际上没有等待
我有一些代码使用Runtime.exec()运行外部.jar(作为IzPack安装程序构建) 如果我像这样从命令行运行external.jar:Java Runtime.exec().waitFor()实际上没有等待,java,multithreading,runtime.exec,Java,Multithreading,Runtime.exec,我有一些代码使用Runtime.exec()运行外部.jar(作为IzPack安装程序构建) 如果我像这样从命令行运行external.jar: java -jar external.jar 然后,在应用程序完成之前,命令提示符不会返回控制。但是,如果我从某个java类中运行external.jar,使用: Process p = Runtime.getRuntime().exec("java -jar external.jar"); int exitCode = p.waitFor(); S
java -jar external.jar
然后,在应用程序完成之前,命令提示符不会返回控制。但是,如果我从某个java类中运行external.jar,使用:
Process p = Runtime.getRuntime().exec("java -jar external.jar");
int exitCode = p.waitFor();
System.out.println("Process p returned: " + exitCode);
然后p
几乎立即返回,成功代码为0
,尽管external.jar尚未完成执行(我还通过外部文件执行的ProcessBuilder
路径尝试了这一点)
为什么它要等待从命令行返回,而不是从另一个java程序中执行
我还设置了3个JAR,A、B和C,其中A调用B调用C(使用Runtime.exec()
),其中CThread.sleep
s持续10秒,作为一个简单的测试,正如预期的那样,A在运行10秒后才会返回
我认为这可能是external.jar的线程问题,执行从一件事转移到另一件事,但考虑到它直接从命令行工作,我有点希望在从另一个java程序调用时看到相同的行为(可能很幼稚)
我已经用Java6在Windows和Ubuntu上测试过了
谢谢 您是否正在生成一个新线程来处理进程的生成?如果是这样,原始区域程序将继续独立于生成的进程运行,因此waitFor()将只在新进程上工作,而不在父进程上工作。
进程。waitFor()对于某些本机系统命令无效
您需要获取进程的输出以确定它是否返回
我为您编写了一个示例代码
/**
*
* @param cmdarray command and parameter of System call
* @param dir the directory execute system call
* @param returnImmediately true indicate return after system call immediately;
* false otherwise.
* if set true, the returned call result does not have reference value
* @return the return code of system call , default is -1
*/
public static int systemCall(String[] cmdarray,File dir,boolean returnImmediately)
{
int result = -1;
try {
Process p = Runtime.getRuntime().exec(cmdarray,null,dir);
if(!returnImmediately)
{
java.io.InputStream stdin = p.getInputStream();
java.io.InputStreamReader isr = new java.io.InputStreamReader(stdin);
java.io.BufferedReader br = new java.io.BufferedReader(isr);
String line = null;
while ( (line = br.readLine()) != null)
System.out.println(line);
}
try{result = p.exitValue();}
catch(Exception ie){;}
} catch (IOException e) {
e.printStackTrace();}
return result;
}
public static void main(String[] argc){
String[] cmdarray = {"jar","cvf","s2.jar","*"};
File dir = new File("D:\\src\\struts-2.3.1");
int k = systemCall(cmdarray,dir,true);
System.out.println("k="+k);
}
我使用processs在控制台上执行一些软件时遇到了同样的问题,我只是使用process.waitFor()解决了这个问题
对我来说,它工作得很好
try{
Process tr = Runtime.getRuntime().exec( new String[]{ "wkhtmltopdf",frontPage,frontPagePDF});
tr.waitFor();
} catch (Exception ex) {
EverLogger.logEntry("Error al pasar a PDF la portada", "error", "activity");
return;
}
some more code here.
实现这一点的另一种可能的方法是捕获流程的输出并等待它完成
例如:
Process tr = Runtime.getRuntime().exec( new String[]{"wkhtmltopdf",mainPage,mainPagePDF});
BufferedReader stdOut=new BufferedReader(new InputStreamReader(tr.getInputStream()));
String s;
while((s=stdOut.readLine())!=null){
//nothing or print
}
通常,输出流是tr.getInputStream(),但根据您正在执行的程序,流程输出流可能是:
- tr.getInputStream()
- tr.getErrorStream()
- tr.getOutputStream()
通过执行此while循环,您可以强制程序等待进程完成。您可以使用process Builder
ProcessBuilder pb = new ProcessBuilder("java", "-jar", "/fielname.jar");
Process p = pb.start();
p.waitFor();
据我所知,whatFor()
将等待您启动的进程结束,这意味着所有非守护进程线程都已完成,因此我怀疑这是否仅仅是线程问题。我想知道你调用的jar本身是否调用了一个外部进程然后退出。你怎么知道它还没有完成?您仍然在进程列表中看到jar吗?这不太可能,有没有可能其他线程正在您的process
字段上调用notify()
?这就是waitFor()
在UNIXProcess
中所做的,至少.external.jar生成了一个自己的控制台窗口,然后该窗口运行在自己的各种System.out.println
中,记录其执行过程。当返回退出代码时,这个日志记录仍然在继续(另外,我知道做任何事情都需要30秒左右,而返回几乎是瞬时的)。也许这与气垫船的建议有关?格雷-进程p
完全独立于一个方法调用中,除了上面描述的之外,它不做任何其他事情,因此没有其他与它的交互。不,这一切都发生在一个线程中,即,我可以在调用方法中线程。睡眠
,让我的应用程序睡眠,这就是我目前正在做的工作,通过睡眠来解决这个问题,直到满足某些外部参数(如现有的某些文件)。不过,这并不理想。“对于某些本机系统命令来说是无用的”它还有什么用途?您的开始争论需要一些支持证据或推理,而您的代码是错误的,因为您没有使用进程的错误流;您没有关闭它的输入流;如果进程尚未退出,则忽略exitValue()引发的异常-这对我来说确实有效。waitFor()立即返回(例如,因为主线程已结束),但只要进程未完全终止,流将保持可访问状态。无法使用输入和错误流不会导致挂起吗?