4

我有一个带有 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;
}
}

和主类我使用执行器

   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继续运行

请任何人给我这个问题的解决方案!

4

3 回答 3

2

您等待objectFuture isDone方法完成。根据文档:

isDone:如果此任务完成,则返回 true。完成可能是由于正常终止、异常或取消——在所有这些情况下,此方法将返回 true

发生异常时查看 processB 中的代码,您将call()再次递归执行。我知道您这样做是一种错误重试机制,但这是一个非常糟糕的主意,主要有两个原因: - 如果异常仍然存在,您最终会得到一个StackOverflowException. - 不满足任何条件isDone

更好的选择是定义最大重试次数并尝试执行mutator.execute()。如果错误仍然存​​在,则抛出异常并完成执行。

另一种选择是等待 processB 完成最长时间,然后通过调用取消任务的执行objectFuture.cancel(true)

关于 processA 的一些评论:在RunTask您不使用runParams这似乎是一些需要作为字符串导入的文件时。此外,您使用readLine()on DataInputStreamwhich 是一种已弃用的方法。而是使用InputStream(例如BufferedInputStream)包裹在 an 中InputStreamReader,然后包裹在-BufferedReader然后调用readLine().BufferedReader

于 2012-06-09T09:29:48.997 回答
1

我在生成 exec 时遇到的一件事是,如果发生错误并且我没有设置线程来读取 ErrorStream,那么 ErrorStream 缓冲区可能会填满,此时一切都会停止等待我从 ErrorStream 缓冲区中清除一些文本。在我这样做之前,进程 B 不能再写任何错误,进程 A 正在等待进程 B 完成。

我的经验的最终结果:当你 exec() 时,总是设置一个线程来读取每个 InputStream 和 ErrorStream。

于 2012-06-09T05:17:12.930 回答
1

printStackTrace将打印到标准错误,而不是标准输出。您还需要读取标准错误(这很棘手 - 您需要 2 个线程,每个流一个),或者改为打印到标准输出 ( printStackTrace(System.out))。

于 2012-06-09T05:18:23.663 回答