0

我有两个使用 CommonsExec 执行的调用——一个是标准的同步调用,其中我调用一个批处理文件来编译一个 maven 项目,下一个是对运行已编译命令行项目的批处理文件的异步调用。

Maven批处理文件看起来像

call mvn package

这样做两次,以编译和启动两个程序。

这第一次工作正常,但第二次同步构建调用由于某种原因没有返回,尽管记录的输出显示构建成功完成。该程序显然没有启动。

我也可以通过运行然后编译来重新创建它 - 似乎只要异步调用正在运行,同步调用就不会完成。

有人可以在这里帮忙吗?

上面的代码是

 private static final String LAUNCH_CLIENT_FORMAT = "\"%s\\start.bat\" http://localhost:%d" + ENDPOINT;
 private static final String COMPILE_FORMAT = "\"%s\\compile.bat\"";

 private static boolean compileAndLaunch(String aiDirectory, int port) {
   System.out.println("Compiling " + aiDirectory + " for port " + port);
   if (!run(String.format(COMPILE_FORMAT, aiDirectory), aiDirectory))
     return false;

   System.out.println("Done compiling " + aiDirectory + " for port " + port + ", launching...");
   if (!runAsync(String.format(LAUNCH_CLIENT_FORMAT, aiDirectory, port), aiDirectory))
     return false;

   return true;
 }

 private static boolean run(String command, String directory) {
   DefaultExecutor executor = getExecutor(directory);
   System.out.println("Running " + command);
   CommandLine commandLine = CommandLine.parse(command);
   try {
     executor.execute(commandLine);
   }
   catch (ExecuteException e) {
     System.out.println("Failed to execute " + command);
     return false;
   }
   catch (IOException e) {
     System.out.println("IO Exception running " + command);
     return false;
   }
   return true;
 }

 private static DefaultExecutor getExecutor(String directory) {
   ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
   PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream);
   DefaultExecutor executor = new DefaultExecutor();
   executor.setWorkingDirectory(new File(directory));
   executor.setStreamHandler(streamHandler);
   return executor;
 }

 private static boolean runAsync(String command, String directory) {

   CommandLine commandLine = CommandLine.parse(command);
   System.out.println("Running async " + command);
   DefaultExecutor executor = getExecutor(directory);
   DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
   try {
     executor.execute(commandLine, resultHandler);
   }
   catch (ExecuteException e) {
     System.out.println("Failed to execute " + command);
     return false;
   }
   catch (IOException e) {
     System.out.println("IO Exception running " + command);
     return false;
   }
   return true;
 }
4

1 回答 1

2

这是您的回调:

DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();

这是你的异步执行器:

executor.execute(commandLine, resultHandler);

但是,在异步模式下,在调用executor.execute()该方法之后将继续,但是直到另一个线程中发生某些事情并且resultHandler.onProcessComplete()或被resultHandler.onProcessFailed()调用,您仍然不知道执行是否结束,并且不应该退出您的 runAsync() 方法。

我相信将您的方法更改为这样的方法会起作用:

private static boolean runAsync(String command, String directory) {

   CommandLine commandLine = CommandLine.parse(command);
   System.out.println("Running async " + command);
   DefaultExecutor executor = getExecutor(directory);
   DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
   try {
     executor.execute(commandLine, resultHandler);
     resultHandler.waitFor();
     if(resultHandler.getException() != null){
       throw resultHandler.getException();
     }
   }
   catch (ExecuteException e) {
     System.out.println("Failed to execute " + command);
     return false;
   }
   catch (IOException e) {
     System.out.println("IO Exception running " + command);
     return false;
   }
   return true;
 }

因为resultHandler.waitFor()会让线程一直等到执行结束。

但这与使用同步模式相同。只有当两个调用都是异步的时,你才会在性能上获胜,因为它们会并行运行,而你会一直等到两个调用都完成。

于 2013-07-11T02:04:04.917 回答