我有一个带有2个进程java的程序:processA和processB(2进程java.exe不是2个线程)。 我使用进程A下面的代码块来调用processB,这段代码包含在
下面的RunTask类中public class RunTask implements Callable<Object> {
private String runParams;
public String getRunParams() {
return runParams;
}
public void setRunParams(String runParams) {
this.runParams = runParams;
}
@Override
public Object call() throws Exception {
try {
//System.out.println("run:" + runParams);
Process procB = Runtime.getRuntime().exec("java -jar processB.jar);
DataInputStream ls_in = new DataInputStream(procB.getInputStream());
String ls_str;
while ((ls_str = ls_in.readLine()) != null) {
System.out.println(ls_str);
}
} catch (Exception exp) {
exp.printStackTrace();
}
return null;
}
}
和Main class我使用执行器
ExecutorService eservice = Executors.newSingleThreadExecutor();
while (1 == 1) {
String stringParams = getFilesNeedToImportAsString();
if (stringParams.trim().isEmpty()) {
long l1 = System.currentTimeMillis() - l;
System.out.println("all time" + l1 / 1000);
System.exit(100);
}
RunTask runTask = new RunTask();
runTask.setRunParams(SystemInfo.RUN_COMMAND + stringParams);
Future<Object> objectFuture = eservice.submit(runTask);
while (!objectFuture.isDone()) {
System.out.println("waiting the task running");
Thread.sleep(500);
}
}
但是当processB上发生异常时,两个进程(processA,processB)似乎都停止了,这就是在processB上运行的代码
public Object call() {
try {
MutationResult result = mutator.execute();
return "ok";
} catch (Exception exp) {
exp.printStackTrace();
System.out.println("error on " + Thread.currentThread().getName() + "failed begin retry " + (++retryCount));
call();
System.out.println(retryCount + " completed");
return "ok";
}
}
如果我单独运行processB(通过命令行)它永远不会发生,或者当发生此问题时我使用taskmanager来杀死proceesA(被调用者),processB继续运行
请任何人给我这个问题的解决方案!!
答案 0 :(得分:2)
您等待objectFuture
isDone
方法完成。根据文件:
isDone:如果此任务完成,则返回true。完成可能是由于 正常终止,例外或取消 - 在所有这些中 例如,此方法将返回true
查看发生异常时processB中的代码,再次递归执行call()
。我知道你这样做是一种错误重试机制,但这有两个主要原因,这是一个非常糟糕的主意:
- 如果异常仍然存在,您最终会获得StackOverflowException
。
- isDone
的任何条件都不会得到满足。
更好的替代方案是定义最大重试次数并尝试执行mutator.execute()
。如果错误仍然存在,则抛出异常并完成执行。
另一个选择是等待processB完成最长时间,然后通过调用objectFuture.cancel(true)
取消执行任务。
关于processA的几条评论:在RunTask
上,您不使用runParams
,这些文件似乎是一些需要作为字符串导入的文件。此外,您在readLine()
上使用DataInputStream
这是一种弃用的方法。而是使用包裹在InputStream
中的BufferedInputStream
(例如InputStreamReader
),然后将其包裹在BufferedReader
中 - 然后在readLine()
上调用BufferedReader
。
答案 1 :(得分:1)
我在生成exec时遇到的一件事就是,如果发生错误并且我没有设置线程来读取ErrorStream,那么ErrorStream缓冲区可以填满,此时所有内容都会变为停止等待我清除ErrorStream缓冲区中的一些文本。在我执行之前,进程B不能再写错误,并且进程A正在等待进程B完成。
我的经验的最终结果:当你执行exec()时,总是设置一个线程来读取每个InputStream和ErrorStream。
答案 2 :(得分:1)
printStackTrace
将打印到标准错误,而不是标准错误。您还需要读取标准错误(这很棘手 - 您需要2个线程,每个流一个),或者打印到标准输出(printStackTrace(System.out)
)。