Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中进行多个异步调用时,如何忽略失败的CompletableFuture调用?_Java_Spring_Multithreading_Asynchronous_Exception - Fatal编程技术网

在Java中进行多个异步调用时,如何忽略失败的CompletableFuture调用?

在Java中进行多个异步调用时,如何忽略失败的CompletableFuture调用?,java,spring,multithreading,asynchronous,exception,Java,Spring,Multithreading,Asynchronous,Exception,我想在Java中使用三个REST服务并行调用,代码如下: private CompletableFuture < EmployeesListResponse > makeAsyncCall(Request request) { return CompletableFuture.supplyAsync( () -> { try { LOGGER.warn("- - - - - Employees Service async call - - - -

我想在Java中使用三个REST服务并行调用,代码如下:

private CompletableFuture < EmployeesListResponse > makeAsyncCall(Request request) {
 return CompletableFuture.supplyAsync(
  () -> {
   try {
    LOGGER.warn("- - - - - Employees Service async call - - - - -");
    return serviceObj.findServiceImpl(request);
   } catch (Exception e) {
    LOGGER.warn("service async call failed...", e);
   }
   return null;
  }, asyncExecutor).handle((res, ex) -> {
  LOGGER.warn("Exceptionally...", ex.toString(), res.toString());
  return new EmployeesListResponse();
 });
}

CompletableFuture < EmployeesListResponse > asyncFirstCall = makeAsyncCall(request);
CompletableFuture < EmployeesListResponse > asyncSecondCall = makeAsyncCall(request);
CompletableFuture < EmployeesListResponse > asyncThirdCall = makeAsyncCall(request);

CompletableFuture.allOf(asyncFirstCall, asyncSecondCall, asyncThirdCall).join();
private CompletableFuturemakeAsyncCall(请求){
返回CompletableFuture.SupplySync(
() -> {
试一试{
LOGGER.warn(“----员工服务异步调用-”;
返回serviceObj.findServiceImpl(请求);
}捕获(例外e){
LOGGER.warn(“服务异步调用失败…”,e);
}
返回null;
}句柄((res,ex)->{
LOGGER.warn(“异常…”,例如toString(),res.toString());
返回新员工响应();
});
}
CompletableFutureasyncFirstCall=MakeSyncCall(请求);
CompletableFutureasyncSecondCall=MakeSyncCall(请求);
CompletableFutureasyncThirdCall=MakeSyncCall(请求);
CompletableFuture.allOf(asyncFirstCall、asyncSecondCall、asyncThirdCall).join();
在上面的代码中,我进行了三个调用,并使用
CompletableFuture.allOf().join()
加入它们。当所有三个调用的服务响应都为200 OK时,此代码工作正常

如果一个调用失败(
500内部服务器错误或404找不到
),而另外两个服务调用200正常,则代码将引发异常,整个API响应将因异常而失败。在这种情况下,我希望忽略一个异常服务调用,并从其他两个调用返回成功响应


在这种情况下,如何处理忽略异常?

因此,您试图等待所有3个期货完成后再完成,但当单个期货失败时,所有期货将立即返回。相反,您可以显式地等待以下各项:

List<CompletableFuture<String>> allFutures = Arrays.asList(asyncFirstCall, asyncSecondCall,
        asyncThirdCall);
// await completion of all futures
allFutures.forEach(future -> {
    try {
        future.join();
    } catch (CompletionException ex) {
        // handled below.
    }
});

if (allFutures.stream().filter(CompletableFuture::isCompletedExceptionally).count() > 2) {
    throw new RuntimeException("Multiple failures");
}

// else continue with your business logic...
List allFutures=Arrays.asList(asyncFirstCall、asyncSecondCall、,
异步调用);
//等待所有期货交易完成
allFutures.forEach(未来->{
试一试{
future.join();
}catch(CompletionException-ex){
//下面处理。
}
});
if(allFutures.stream().filter(CompletableFuture::isCompletedExceptionally).count()>2){
抛出新的RuntimeException(“多次失败”);
}
//否则请继续您的业务逻辑。。。

您不需要在try-catch块中处理异常,因为您已经在处理handle()方法。无论是否获得异常,每次都将执行此handle()方法。您只需要检查是否存在任何异常,如果是,则根据需要发送默认响应

private CompletableFuture < EmployeesListResponse > makeAsyncCall(Request request) {
     return CompletableFuture.supplyAsync(
      () -> {
        LOGGER.warn("- - - - - Employees Service async call - - - - -");
        return serviceObj.findServiceImpl(request);
      }, asyncExecutor).handle((res, ex) -> {
          if (ex != null) {
              LOGGER.warn("Exceptionally...", ex);
              return "what ever default you want to return";
   //         or return new EmployeesListResponse();
            }
            return res;
     });
    }
private CompletableFuturemakeAsyncCall(请求){
返回CompletableFuture.SupplySync(
() -> {
LOGGER.warn(“----员工服务异步调用-”;
返回serviceObj.findServiceImpl(请求);
}句柄((res,ex)->{
如果(ex!=null){
记录器。警告(“异常…”,例如);
返回“您想要返回的默认值”;
//或返回新员工响应();
}
返回res;
});
}

如果要忽略,请尝试以下操作

CompletableFuture<Void> allOf = CompletableFuture.allOf(asyncFirstCall,asyncSecondCall);
allOf.whenComplete((aVoid, throwable) -> {
    allOf.join();
});
CompletableFuture allOf=CompletableFuture.allOf(asyncFirstCall,asyncSecondCall);
全部完成时((避免,可丢弃)->{
allOf.join();
});

非常感谢!这对于处理异常和从其他成功调用中获得部分响应非常有用。当我等待每个将来加入上面提到的forEach时,restweb服务的响应时间会有延迟吗?因为当我使用allOf()时,响应时间大约是6秒,现在大约是10秒。你能告诉我这是否是代码中潜在的性能问题吗?还有一种方法,我们可以知道异常ex类型是HttpStatusException或ClientErrorException等,以知道错误是404还是500。如果我得到所有的500,那么我必须抛出一个自定义异常,如果其中任何一个是404,那么我必须抛出一个不同的自定义异常,如果其中任何一个是200,我将一如既往地继续。我不会期望有显著的性能差异,可能你只是看到了噪音。当然,除了在失败案例中,你以前失败得更快。通过查看
ex.cause()
,您可以检查底层异常的类型。Eclipse IDE正在强制围绕返回serviceObj.findServiceImpl(请求);使用try-catch块,即使我们使用.handle(),所以我使用了try-catch,现在删除了.handle()