有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何执行CompletableFuture函数并得到结果,或者先执行哪一个?

我已经创建了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


共 (1) 个答案

  1. # 1 楼答案

    你的两次尝试都不起作用,因为你在没有等待结果的情况下调用了一个完成阶段(不过我不确定尝试1)

    我不知道所有方法的签名,但是如果在某处您在supplyAsync中返回一个CompletionStage,并且您没有使用thenCompose,那么函数将忽略CompletionStage的结果而返回

    在第二次尝试中,更容易看出错误所在。这一部分:

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

    你在thenRun部分做什么并不重要。您不需要在任何地方等待结果,因此它将立即到达return transSalesOrdersResponseNew;,即使您在thenRun部分中定义的函数尚未完成

    假设方法findSOHaveItemLeftOverOnlyfindPureUnAssignedSOfindSalesOrderWithBpsjInDeliveryOrder是正确的(我们无法从您提供的详细信息中知道这一点),您可以这样重写代码:

    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。这样你就不会在过程中失去结果

    您还可以使用CompletableFuture.allOf并行运行find方法(如果顺序不重要),但在这种情况下,您需要确保使用线程安全的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;