2012-06-09 31 views
4

我有一个程序,其中有2个进程java:processA和processB(2个进程java.exe不是2个线程)。 我用下面的代码块从过程A至调用进程B这个代码被包裹在RunTask类下面从另一个java进程调用java使其停止

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; 
} 
} 

和主要类别I执行人

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); 
      } 
     } 

但是,当异常发生在进程B这两个进程( processA,进程B)似乎被暂停在进程B这是代码的运行

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"; 
    } 

} 

如果我运行进程B单独(通过命令行站),它永远不会发生,或当这个问题发生我使用taskmanager杀死proceesA(被调用者),processB继续运行

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

回答

2

您等待objectFutureisDone方法来完成。根据文档:

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

在进程B的代码寻找在发生异常时您执行call()再次递归​​。我明白,你这样做是一个错误重试机制,但这是一个非常糟糕的主意,主要有两个原因: - 如果异常仍然存在,您将最终得到StackOverflowException。 - 将不符合isDone的条件。

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

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

对processA的一些评论:在RunTask你不使用runParams这似乎是一些需要作为字符串导入的文件。此外,您使用readLine()DataInputStream这是一个不赞成使用的方法。取而代之的是使用InputStream(例如BufferedInputStream)包裹在InputStreamReader中,然后包裹在BufferedReader中 - 然后在BufferedReader上调用readLine()

+0

感谢spaniard StackOverflowException可能发生在这里!我已经修复了它:D:D –

1

当产生exec时遇到的一件事是,如果发生错误,并且我没有设置线程来读取ErrorStream,那么ErrorStream缓冲区可以填满,在这一点上,所有东西都会磨合暂停等待我清除ErrorStream缓冲区中的一些文本。进程B在我执行之前不能再写入错误,而进程A正在等待进程B完成。

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

1

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