Java 8 completable future可并行执行方法

Java 8 completable future可并行执行方法,java,java-8,completable-future,Java,Java 8,Completable Future,我有3个方法需要并行运行,因为它们彼此独立,并在最后合并每个方法的结果,并将其作为响应发送。我还需要处理异常 在不同的帖子中,我找到了下面的代码并进行了相应的修改 public Response getResponse() { Response resultClass = new Response(); try { CompletableFuture<Optional<ClassA>> classAFuture = Completab

我有3个方法需要并行运行,因为它们彼此独立,并在最后合并每个方法的结果,并将其作为响应发送。我还需要处理异常

在不同的帖子中,我找到了下面的代码并进行了相应的修改

public Response getResponse() {
    Response resultClass = new Response();
   try {
    CompletableFuture<Optional<ClassA>> classAFuture
        = CompletableFuture.supplyAsync(() -> service.getClassA() );
    CompletableFuture<ClassB> classBFuture
        = CompletableFuture.supplyAsync(() -> {
             try {
                   return service.getClassB(); 
              }
              catch (Exception e) {
                   throw new CompletionException(e);
              }
     });
    CompletableFuture<ClassC> classCFuture
        = CompletableFuture.supplyAsync(() -> { 
            try {
                return service.getClassC();
            } catch (Exception e) {
                throw new CompletionException(e);
            }
    });

   CompletableFuture<Response> responseFuture =
    CompletableFuture.allOf(classAFuture, classBFuture, classCFuture)
         .thenApplyAsync(dummy -> {
            if (classAFuture.join().isPresent() {
               ClassA classA = classAFuture.join();
               classA.setClassB(classBFuture.join());
               classA.setClassC(classCFuture.join());
               response.setClassA(classA)
             }
            return response;
         });
   responseFuture.join();
  } catch (CompletionExecution e) {
    throw e;
  }
  return response;
}
public Response getResponse(){
Response resultClass=新响应();
试一试{
完整的未来类别未来
=CompletableFuture.SupplySync(()->service.getClassA());
完全未来类未来
=CompletableFuture.SupplySync(()->{
试一试{
return service.getClassB();
}
捕获(例外e){
抛出新的CompletionException(e);
}
});
完全未来类未来
=CompletableFuture.SupplySync(()->{
试一试{
return service.getClassC();
}捕获(例外e){
抛出新的CompletionException(e);
}
});
完全的未来反应未来=
CompletableFuture.allOf(classAFuture,classBFuture,classCFuture)
.然后应用同步(虚拟->{
if(classAFuture.join().isPresent()){
ClassA ClassA=classAFuture.join();
setClassB(classBFuture.join());
classA.setClassC(classCFuture.join());
response.setClassA(classA)
}
返回响应;
});
responseFuture.join();
}捕获(完成执行e){
投掷e;
}
返回响应;
}

上述方法是否应该并行运行?我发现这需要更多的时间,我想确保我做得正确。

如果要并行运行方法,应该使用ExecutorService。请尝试类似的方法:

ExecutorService myExecutor = Executors.newFixedThreadPool(3);
        List<Future<Object>> futures = myExecutor.invokeAll(
            Arrays.asList(
                () -> service.getClassA(),
                () -> service.getClassB(),
                () -> service.getClassC(),
            )
        );
        myExecutor.shutdown();
ExecutorService myExecutor=Executors.newFixedThreadPool(3);
列表期货=myExecutor.invokeAll(
Arrays.asList(
()->service.getClassA(),
()->service.getClassB(),
()->service.getClassC(),
)
);
myExecutor.shutdown();

如果要并行运行方法,应使用ExecutorService。请尝试以下操作:

ExecutorService myExecutor = Executors.newFixedThreadPool(3);
        List<Future<Object>> futures = myExecutor.invokeAll(
            Arrays.asList(
                () -> service.getClassA(),
                () -> service.getClassB(),
                () -> service.getClassC(),
            )
        );
        myExecutor.shutdown();
ExecutorService myExecutor=Executors.newFixedThreadPool(3);
列表期货=myExecutor.invokeAll(
Arrays.asList(
()->service.getClassA(),
()->service.getClassB(),
()->service.getClassC(),
)
);
myExecutor.shutdown();

这个想法是正确的,但这一切都可以用更少的代码来完成:

  public Response getResponse() {
    CompletableFuture<Optional<ClassA>> classAFuture = CompletableFuture.supplyAsync(() -> service.getClassA());
    CompletableFuture<ClassB> classBFuture = CompletableFuture.supplyAsync(() -> service.getClassB());
    CompletableFuture<ClassC> classCFuture = CompletableFuture.supplyAsync(() -> service.getClassC());
    
    try {
      return CompletableFuture.allOf(classAFuture, classBFuture, classCFuture)
        .thenApply(() -> {
          Response response = new Response();
          Optional<ClassA> maybeA = classAFuture.get();
          if (maybeA.isPresent()) {
            ClassA classA = maybeA.get();
            classA.setClassB(classBFuture.get());
            classA.setClassC(classCFuture.get());
            response.setClassA(classA);
          }
          return response;
        }).get();
    } catch (ExecutionException e) { // Ususally the exception is wrapped to ExecutionException by java concurrency framework itself
        Throwable cause = e.getCause();
        if (cause != null) {
          throw cause;
        } else {
          throw e;
        }
    }
  }
public Response getResponse(){
CompletableFuture classAFuture=CompletableFuture.SupplySync(()->service.getClassA());
CompletableFuture-classBFuture=CompletableFuture.supplyAsync(()->service.getClassB());
CompletableFuture类未来=CompletableFuture.SupplySync(()->service.getClassC());
试一试{
返回CompletableFuture.allOf(classAFuture,classBFuture,classCFuture)
。然后应用(()->{
响应=新响应();
可选的maybeA=classAFuture.get();
if(maybeA.isPresent()){
ClassA ClassA=maybeA.get();
setClassB(classBFuture.get());
setClassC(classCFuture.get());
回复:setClassA(classA);
}
返回响应;
}).get();
}catch(ExecutionException){//通常,java并发框架本身会将异常包装为ExecutionException
可丢弃的原因=e.getCause();
如果(原因!=null){
抛出原因;
}否则{
投掷e;
}
}
}
主要事项:

  • 您不需要将异常包装到
    CompletionException
  • 您不需要使用
    然后applyasync
    。除非您想非常具体地说明要使用的线程类型,否则使用
    然后apply
    是一样的。有关详细信息,请查看此项
  • 您不需要
    join()
    任何操作。当
    CompletableFuture.all
    完成时,您可以非常确定所有提供的作业都已完成,然后调用
    get()
    将只返回值

  • 至于你能确定作业A、B和C将并行运行吗?是和否。如果有足够的系统资源并行运行它们,它将并行运行。你已经尽了最大努力让它们并行运行。也许在某个时候你还想提供自定义线程池以获得更多控制,但这是另一天的主题。这个想法是正确的,但这一切都可以用更少的代码来完成:

      public Response getResponse() {
        CompletableFuture<Optional<ClassA>> classAFuture = CompletableFuture.supplyAsync(() -> service.getClassA());
        CompletableFuture<ClassB> classBFuture = CompletableFuture.supplyAsync(() -> service.getClassB());
        CompletableFuture<ClassC> classCFuture = CompletableFuture.supplyAsync(() -> service.getClassC());
        
        try {
          return CompletableFuture.allOf(classAFuture, classBFuture, classCFuture)
            .thenApply(() -> {
              Response response = new Response();
              Optional<ClassA> maybeA = classAFuture.get();
              if (maybeA.isPresent()) {
                ClassA classA = maybeA.get();
                classA.setClassB(classBFuture.get());
                classA.setClassC(classCFuture.get());
                response.setClassA(classA);
              }
              return response;
            }).get();
        } catch (ExecutionException e) { // Ususally the exception is wrapped to ExecutionException by java concurrency framework itself
            Throwable cause = e.getCause();
            if (cause != null) {
              throw cause;
            } else {
              throw e;
            }
        }
      }
    
    public Response getResponse(){
    CompletableFuture classAFuture=CompletableFuture.SupplySync(()->service.getClassA());
    CompletableFuture-classBFuture=CompletableFuture.supplyAsync(()->service.getClassB());
    CompletableFuture类未来=CompletableFuture.SupplySync(()->service.getClassC());
    试一试{
    返回CompletableFuture.allOf(classAFuture,classBFuture,classCFuture)
    。然后应用(()->{
    响应=新响应();
    可选的maybeA=classAFuture.get();
    if(maybeA.isPresent()){
    ClassA ClassA=maybeA.get();
    setClassB(classBFuture.get());
    setClassC(classCFuture.get());
    回复:setClassA(classA);
    }
    返回响应;
    }).get();
    }catch(ExecutionException){//通常,java并发框架本身会将异常包装为ExecutionException
    可丢弃的原因=e.getCause();
    如果(原因!=null){
    抛出原因;
    }否则{
    投掷e;
    }
    }
    }
    
    主要事项:

  • 您不需要将异常包装到
    CompletionException