如何在春季使用CompletableFuture链接异步调用和传播异常

时间:2019-07-25 02:27:08

标签: java spring multithreading asynchronous completable-future

我是多线程和CompletableFuture的新手,我想知道是否可以在Spring容器(Spring Boot 2)和@Async中实现以下方案。

我有几个基本构造一个较大对象的服务,我想看看是否可以使粒度服务异步运行。

我有一个服务(ServiceC)取决于另一个服务(ServiceA)的输出,而第三个服务可以独立运行(ServiceB)。所有其他服务都需要someService,所以我认为不需要将其设为异步调用。下面是布局:

@Service
public class ServiceA {
  @Async
  public CompletableFuture<A> doServiceAWork(int id) throws AppException {
    return CompletableFuture.completedFuture(getA(id));
  }
}


@Service
public class ServiceB {
  @Async
  public CompletableFuture<B> doServiceBWork(int id) {
    return CompletableFuture.completedFuture(getB(id));
  }
}


@Service
public class ServiceC {
  @Async
  public CompletableFuture<C> doServiceCWork(A a) {
    return CompletableFuture.completedFuture(getC(a));
  }
}

@Service
public class ServiceOrchestration {
  // Necessary autorwiring of services

  public BigObj constructBigObj(AppObj obj) throw SomeAppException {
    int id = someService.getId(obj);
    BigObj bigObj = new BigObj();

    try {
      // Conceptualizing here
      CompletableFuture<A> cfA = serviceA.doServiceAWork(id);
      CompletableFuture<B> cfB = serviceB.doServiceBWork(id);

      // Obviously C depends on A
      CompletableFuture<C> cfC = serviceB.doServiceCWork(cfA.get());

      CompletableFuture.allOf(cfA, cfB, cfC).join();

      bigObj.setA(cfA.get());
      bigObj.setB(cfB.get());
      bigObj.setC(cfC.get());

    } catch (AppException | ExecutionException | InterruptedException e) {
      throw new SomeAppException("..", e);
    }

    return BigObj;
  }
}

我的要求如下:

  • 在完成ServiceC后调用对ServiceA的异步调用,因为返回的数据应被馈送到ServiceC以便继续进行

  • 如果对ServiceA的调用引发异常(AppException),则需要将该异常传播给调用方-在这种情况下,ServiceOrchestration#constructBigObject()将按上述方式处理。换句话说,如果serviceA.doServiceAWork(id)引发异常,则应取消所有其他异步调用,但应在constructBigObj中引发异常,以便捕获并处理

  • 等待所有异步调用完成,然后构造BigObj

对于第二个要求,我查看了isCompletedExceptionally(),但不确定例如从哪里调用它。在致电join()之前?那我怎么得到根异常?

异步链接如何在ServiceA调用和ServiceC之间进行工作,这里有调用一个依赖项,同时,我需要两者中的值,例如AC来构造BigObj

0 个答案:

没有答案