java—如何执行completablefuture函数并得到结果—哪一个先执行?

dhxwm5r4  于 2021-07-26  发布在  Java
关注(0)|答案(1)|浏览(417)

我已经创建了3个对数据库执行查询的函数,然后我想得到每个结果并将其添加到一个对象列表中,但是结果总是空的,如何才能正确地做到这一点?我是这样做的:
我创建了3个可完成的未来函数:

  1. private CompletableFuture<List<TransSalesOrderOnlyResponseDto>> findPureUnAssignedSO() {
  2. return CompletableFuture.supplyAsync(() -> iSalesOrderMapper.entityToSOOnlyDto(iTransSalesOrderQdslRepository.findUnAssignedSalesOrder()));
  3. }
  4. private CompletableFuture<List<TransSalesOrderOnlyResponseDto>> findSOHaveItemLeftOverOnly() {
  5. return CompletableFuture.supplyAsync(() -> {
  6. List<TransSalesOrder> transSalesOrders = iTransSalesOrderQdslRepository.findSOHaveLeftOverButDone();
  7. return buildTransSalesOrdersResponseNew(transSalesOrders);
  8. });
  9. }
  10. private CompletableFuture<List<TransSalesOrderOnlyResponseDto>> findSalesOrderWithBpsjInDeliveryOrder() {
  11. return CompletableFuture.supplyAsync(() -> {
  12. List<TransSalesOrder> transSalesOrders = iTransSalesOrderQdslRepository.findSalesOrderWithBpsjInDeliveryOrder();
  13. return buildTransSalesOrdersBpsjOnlyResponseNew(transSalesOrders);
  14. });
  15. }

然后我试着执行3个函数:
尝试1,使用get():

  1. public List<TransSalesOrderOnlyResponseDto> findUnAssignedSO() {
  2. CompletableFuture<List<TransSalesOrderOnlyResponseDto>> future = new CompletableFuture<>();
  3. List<TransSalesOrderOnlyResponseDto> transSalesOrdersResponseNew = new ArrayList<>();
  4. try {
  5. transSalesOrdersResponseNew = findSOHaveItemLeftOverOnly().get();
  6. transSalesOrdersResponseNew.addAll(findPureUnAssignedSO().get());
  7. transSalesOrdersResponseNew.addAll(findSalesOrderWithBpsjInDeliveryOrder().get());
  8. } catch (InterruptedException | ExecutionException e) {
  9. e.printStackTrace();
  10. }
  11. return transSalesOrdersResponseNew;
  12. }

结果仍然是空的
尝试2:

  1. public List<TransSalesOrderOnlyResponseDto> findUnAssignedSO() {
  2. List<TransSalesOrderOnlyResponseDto> transSalesOrdersResponseNew = new ArrayList<>();
  3. CompletableFuture<List<TransSalesOrderOnlyResponseDto>> soHaveItemLeftOverOnly = findSOHaveItemLeftOverOnly();
  4. CompletableFuture<List<TransSalesOrderOnlyResponseDto>> pureUnAssignedSO = findPureUnAssignedSO();
  5. CompletableFuture<List<TransSalesOrderOnlyResponseDto>> salesOrderWithBpsjInDeliveryOrder = findSalesOrderWithBpsjInDeliveryOrder();
  6. CompletableFuture.allOf(soHaveItemLeftOverOnly, pureUnAssignedSO, salesOrderWithBpsjInDeliveryOrder)
  7. .thenRun(() -> {
  8. transSalesOrdersResponseNew.addAll(soHaveItemLeftOverOnly.join());
  9. transSalesOrdersResponseNew.addAll(pureUnAssignedSO.join());
  10. transSalesOrdersResponseNew.addAll(salesOrderWithBpsjInDeliveryOrder.join());
  11. });
  12. }
  13. return transSalesOrdersResponseNew;
  14. }

如果我这样做,结果总是空的,即使我使用.get()来阻止结果,如何正确地执行completablefuture?

kyvafyod

kyvafyod1#

两次尝试都不起作用,因为您在没有等待结果的情况下调用了一个完成阶段(但我不确定尝试1)。
我不知道所有方法的签名,但是如果你在某处返回 CompletionStagesupplyAsync 你不用 thenCompose 相反,函数将忽略completionstage的结果返回
在第二次尝试中,更容易看出哪里错了。这一部分:

  1. CompletableFuture.allOf(...).thenRun(() -> ...);

你在家里做什么并不重要 thenRun 部分。你不会在任何地方等待结果,所以它会到达终点 return transSalesOrdersResponseNew; 即使在 thenRun 部分还没完成。
假设方法 findSOHaveItemLeftOverOnly , findPureUnAssignedSO 以及 findSalesOrderWithBpsjInDeliveryOrder 是正确的(我们无法从您提供的详细信息中得知),您可以这样重写代码:

  1. final List<TransSalesOrderOnlyResponseDto> transSalesOrdersResponseNew = ... ;
  2. findSOHaveItemLeftOverOnly()
  3. .thenAccept( transSalesOrdersResponseNew::addAll )
  4. .thenCompose( v -> findPureUnAssignedSO() )
  5. .thenAccept( transSalesOrdersResponseNew::addAll )
  6. .thenCompose( v -> findSalesOrderWithBpsjInDeliveryOrder() )
  7. .thenAccept( transSalesOrdersResponseNew::addAll )
  8. .join();
  9. return transSalesOrdersResponseNew;

注意,我正在使用 .thenCompose ,这将使用函数的结果作为下一个 CompletionStage 按顺序。这样你就不会在这个过程中失去结果。
您还可以使用并行运行find方法(如果顺序不重要的话) CompletableFuture.allOf 但在这种情况下,您需要确保使用线程安全的list实现。它看起来是这样的:

  1. final List<TransSalesOrderOnlyResponseDto> transSalesOrdersResponseNew = ... // Thread-safe list implementation;
  2. CompletableFuture.allOf(
  3. findSOHaveItemLeftOverOnly().thenAccept( transSalesOrdersResponseNew::addAll ),
  4. findPureUnAssignedSO().thenAccept( transSalesOrdersResponseNew::addAll ),
  5. findSalesOrderWithBpsjInDeliveryOrder().thenAccept( transSalesOrdersResponseNew::addAll )
  6. ).join();
  7. return transSalesOrdersResponseNew;
展开查看全部

相关问题