如何执行 CompletableFuture 函数并获得先完成其中一个的结果?
How to execute CompletableFuture function and get the result either which of them is done first?
我已经创建了 3 个执行数据库查询的函数,然后我想获取每个结果并将其添加到一个对象列表中,但结果始终为空,我该如何正确执行此操作?这是我的工作:
我创建了 3 个 CompletableFuture 函数:
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)。
我不知道所有方法的签名,但是如果你在某个地方 returning supplyAsync
中的 CompletionStage
而你不使用 thenCompose
相反,该函数将 return 忽略 CompletionStage
的结果
在第 2 次尝试中,更容易看出错误的地方。是这部分:
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
。这样你就不会在这个过程中丢失结果。
您也可以 运行 与 CompletableFuture.allOf
并行查找方法(如果顺序无关紧要),但在这种情况下,您需要确保使用线程列表的实现安全的。
它看起来像这样:
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;
我已经创建了 3 个执行数据库查询的函数,然后我想获取每个结果并将其添加到一个对象列表中,但结果始终为空,我该如何正确执行此操作?这是我的工作:
我创建了 3 个 CompletableFuture 函数:
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)。
我不知道所有方法的签名,但是如果你在某个地方 returning supplyAsync
中的 CompletionStage
而你不使用 thenCompose
相反,该函数将 return 忽略 CompletionStage
在第 2 次尝试中,更容易看出错误的地方。是这部分:
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
。这样你就不会在这个过程中丢失结果。
您也可以 运行 与 CompletableFuture.allOf
并行查找方法(如果顺序无关紧要),但在这种情况下,您需要确保使用线程列表的实现安全的。
它看起来像这样:
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;