Java 同时运行Void CompletionStage,但忽略结果

Java 同时运行Void CompletionStage,但忽略结果,java,asynchronous,java-11,completable-future,completion-stage,Java,Asynchronous,Java 11,Completable Future,Completion Stage,我有两个completionStages方法调用,如果不满足条件,每个方法调用一个远程服务。它们都是相当长的运行进程,我们需要减少延迟。我也不关心第二个未来的反应。它可以返回CompletionStage,因为我只关心该方法是否在退出主方法之前运行。更复杂的是,injectedClass2.serviceCall还抛出了一个非常重要的异常(404 StatusRuntimeException),需要向客户端显示该异常 如何确保第一个和第二个future异步运行(不相互依赖),同时第二个futur

我有两个completionStages方法调用,如果不满足条件,每个方法调用一个远程服务。它们都是相当长的运行进程,我们需要减少延迟。我也不关心第二个未来的反应。它可以返回
CompletionStage
,因为我只关心该方法是否在退出主方法之前运行。更复杂的是,
injectedClass2.serviceCall
还抛出了一个非常重要的异常(404 StatusRuntimeException),需要向客户端显示该异常

如何确保第一个和第二个future异步运行(不相互依赖),同时第二个future为客户端显示其错误代码和异常

下面的主要方法是我在这方面的最佳尝试。它可以工作,但我希望学习一种更好的实现,它利用了可完成表/流等

try {
      .
      .
      .
      CompletionStage<Response> firstFuture;
      CompletionStage<Response> secondFuture = CompletableFuture.completedFuture(Response.default());
      if (condition) {
        firstFuture = legacyImplThing.resolve(param1, param2);
      } else {
        firstFuture =
            injectedClass1.longRunningOp(param1, param2);
        secondFuture = injectedClass2.serviceCall(param1, param2, someOtherData);
      }

      final CompletionStage<MainMethodResponse> response =
          CompletableFutures.combine(firstFuture, secondFuture, (a, b) -> a)
              .thenApply(
                  v -> ServiceResponse.newBuilder().setParam(v.toString()).build());

      handleResponse(response, responseObserver);
    } catch (Exception e) {
      responseObserver.onError(e);
    }
试试看{
.
.
.
完成阶段优先于未来;
CompletionStage secondFuture=CompletableFuture.completedFuture(Response.default());
如果(条件){
firstFuture=legacyImpleThing.resolve(param1,param2);
}否则{
第一未来=
注射类1.longRunningOp(参数1,参数2);
secondFuture=injectedClass2.serviceCall(param1、param2、someOtherData);
}
最终完井阶段响应=
CompletableFutures.combine(第一个期货,第二个期货,(a,b)->a)
.然后申请(
v->ServiceResponse.newBuilder().setParam(v.toString()).build());
HandlerResponse(响应,响应观察者);
}捕获(例外e){
响应观察者onError(e);
}
可能超出范围,如何测试/检查两个CompletionStage是否同时运行


编辑:
CompletableFutures.combine()
是第三方库方法,不是java.util.concurrent包的一部分。

链接其他阶段不会改变以前的阶段。换句话说,并行性完全在您的控制之外,因为它已经被确定

更具体地说,当调用
injectedClass1.longRunningOp(param1,param2)
时,方法
longRunningOp
的实现决定了返回的未来将如何完成。同样,当您调用
injectedClass2.serviceCall(param1,param2,someOtherData)
时,
serviceCall的实现将决定返回的未来的完成。这两种方法可以在幕后使用相同的执行者,也可以使用完全不同的方法

唯一可以影响并行性的场景是,这两种方法都在调用方的线程中执行实际操作,最终返回一个已经完成的未来。在这种情况下,您必须将每个调用包装到另一个异步操作中,以使它们并行运行。但在调用方线程中执行长时间操作时返回未来将是一种奇怪的设计

你的代码

CompletableFutures.combine(firstFuture, secondFuture, (a, b) -> a)
不匹配。一个有效的电话是

firstFuture.thenCombine(secondFuture, (a, b) -> a)
在这种情况下,您不会影响
firstFuture
secondFuture
的完成。您只是指定在两个未来都完成后应该发生什么

顺便说一句,没有理由在
中指定一个像
(a,b)->a
这样的简单函数,然后在
中组合
,只是为了链接另一个
然后应用
。你可以用

firstFuture.thenCombine(secondFuture,
    (v, b) -> ServiceResponse.newBuilder().setParam(v.toString()).build())

首先。

不能保证它们同时运行。长时间运行的进程最好由线程处理,而不是由CompletionStages@chrylis-突击-这很有趣,我完全忘记了。你能详细说明一下吗?在我的情况下,我们拥有一致的流量模式和多核机器。但是,即使如此,我仍然需要弄清楚我的未来是否同时运行。