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

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

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

private CompletableFuture<List<TransSalesOrderOnlyResponseDto>> findPureUnAssignedSO() {
    return CompletableFuture.supplyAsync(() -> iSalesOrderMapper.entityToSOOnlyDto(iTransSalesOrderQdslRepository.findUnAssignedSalesOrder()));
}

private CompletableFuture<List<TransSalesOrderOnlyResponseDto>> findSOHaveItemLeftOverOnly() {
    return CompletableFuture.supplyAsync(() -> {
        List<TransSalesOrder> transSalesOrders = iTransSalesOrderQdslRepository.findSOHaveLeftOverButDone();
        return buildTransSalesOrdersResponseNew(transSalesOrders);
    });
}

private CompletableFuture<List<TransSalesOrderOnlyResponseDto>> findSalesOrderWithBpsjInDeliveryOrder() {
    return CompletableFuture.supplyAsync(() -> {
        List<TransSalesOrder> transSalesOrders = iTransSalesOrderQdslRepository.findSalesOrderWithBpsjInDeliveryOrder();

        return buildTransSalesOrdersBpsjOnlyResponseNew(transSalesOrders); 
    });
}

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

public List<TransSalesOrderOnlyResponseDto> findUnAssignedSO() {
    CompletableFuture<List<TransSalesOrderOnlyResponseDto>> future = new CompletableFuture<>();

    List<TransSalesOrderOnlyResponseDto> transSalesOrdersResponseNew = new ArrayList<>();
    try {
        transSalesOrdersResponseNew = findSOHaveItemLeftOverOnly().get();
        transSalesOrdersResponseNew.addAll(findPureUnAssignedSO().get());
        transSalesOrdersResponseNew.addAll(findSalesOrderWithBpsjInDeliveryOrder().get());
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }

    return transSalesOrdersResponseNew;
}

结果仍然是空的
尝试2:

public List<TransSalesOrderOnlyResponseDto> findUnAssignedSO() {
    List<TransSalesOrderOnlyResponseDto> transSalesOrdersResponseNew = new ArrayList<>();

    CompletableFuture<List<TransSalesOrderOnlyResponseDto>> soHaveItemLeftOverOnly = findSOHaveItemLeftOverOnly();
    CompletableFuture<List<TransSalesOrderOnlyResponseDto>> pureUnAssignedSO = findPureUnAssignedSO();
    CompletableFuture<List<TransSalesOrderOnlyResponseDto>> salesOrderWithBpsjInDeliveryOrder = findSalesOrderWithBpsjInDeliveryOrder();

    CompletableFuture.allOf(soHaveItemLeftOverOnly, pureUnAssignedSO, salesOrderWithBpsjInDeliveryOrder)
            .thenRun(() -> {
                transSalesOrdersResponseNew.addAll(soHaveItemLeftOverOnly.join());
                transSalesOrdersResponseNew.addAll(pureUnAssignedSO.join());
                transSalesOrdersResponseNew.addAll(salesOrderWithBpsjInDeliveryOrder.join());
                });

    }

    return transSalesOrdersResponseNew;
}

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

kyvafyod

kyvafyod1#

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

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

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

final List<TransSalesOrderOnlyResponseDto> transSalesOrdersResponseNew = ... ;

findSOHaveItemLeftOverOnly()
   .thenAccept( transSalesOrdersResponseNew::addAll )
   .thenCompose( v -> findPureUnAssignedSO() )
   .thenAccept( transSalesOrdersResponseNew::addAll )
   .thenCompose( v -> findSalesOrderWithBpsjInDeliveryOrder() )
   .thenAccept( transSalesOrdersResponseNew::addAll )
   .join();

return transSalesOrdersResponseNew;

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

final List<TransSalesOrderOnlyResponseDto> transSalesOrdersResponseNew = ... // Thread-safe list implementation;

CompletableFuture.allOf(
    findSOHaveItemLeftOverOnly().thenAccept( transSalesOrdersResponseNew::addAll ),
    findPureUnAssignedSO().thenAccept( transSalesOrdersResponseNew::addAll ),
    findSalesOrderWithBpsjInDeliveryOrder().thenAccept( transSalesOrdersResponseNew::addAll )
).join();

return transSalesOrdersResponseNew;

相关问题