简体   繁体   English

Apache CommonsExec异步调用阻止同步调用

[英]Apache CommonsExec async call preventing sync call

I have two calls that I perform using CommonsExec - one is a standard synchronous call in which I call a batch file to compile a maven project, and the next is a asynchronous call also to a batch file that runs the compiled command line project. 我有两个使用CommonsExec执行的调用 - 一个是标准同步调用,我在其中调用批处理文件来编译maven项目,然后是对运行编译的命令行项目的批处理文件的异步调用。

The maven batch files look like maven批处理文件看起来像

call mvn package

This is done twice, to compile and launch two programs. 这样做了两次,以编译和启动两个程序。

This works fine the first time, but the second sync build call does not return for some reason, although the logged output shows the build completes successfully. 这在第一次正常工作,但第二次同步构建调用由于某种原因没有返回,尽管记录的输出显示构建成功完成。 The program then obviously is not launched. 那么该程序显然没有启动。

I can also recreate this by doing a run, then a compile - it seems that so long as a asynchronous call is running, the synchronous call will not complete. 我也可以通过运行,然后编译来重新创建它 - 似乎只要异步调用正在运行,同步调用就不会完成。

Can anyone help here? 有人可以帮忙吗?

Code for the above is 上面的代码是

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

This is your callback: 这是你的回调:

DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();

This is your asynchronous executor: 这是您的异步​​执行程序:

executor.execute(commandLine, resultHandler);

But, in a asynchronous mode, right after calling executor.execute() the method will continue, but until something happens in another thread and resultHandler.onProcessComplete() or resultHandler.onProcessFailed() are called, you still don't know if the execution ended, and should not exit your runAsync() method. 但是,在异步模式下,在调用executor.execute()该方法将继续,但是直到在另一个线程中发生某些事情并resultHandler.onProcessComplete()resultHandler.onProcessFailed() ,你仍然不知道是否执行结束,不应该退出runAsync()方法。

I believe changing your method to something like this will work: 我相信将你的方法改为这样的方法会起作用:

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

Because resultHandler.waitFor() will make the thread wait until the execution ends. 因为resultHandler.waitFor()将使线程等待直到执行结束。

But this is the same as using the synchronous mode. 但这与使用同步模式相同。 Only if both calls are asynchronous, you would win in performance, because they would run in parallel, and you would be waiting until both finish. 只有当两个调用都是异步的时候,你才会在性能上获胜,因为它们会并行运行,你会等到两个完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM