CompletableFuture.get() 卡住,不返回结果

问题描述 投票:0回答:1

我有一个 Java 代码片段,它使用 CompletableFuture 异步检索数据。

@GetMapping("/voyagePointData/{reportType}")
@PreAuthorize("@generalGuard.isResourceAllowed(authentication, #accountId) && hasAuthority('acl.map.device.READ')")
public ResponseEntity<List<ReportVoyagePointBean>> getVoyagePointData(@RequestParam(value = "accountId") int accountId,
                                                                      @RequestParam(value = "ids") Set<Integer> ids,
                                                                      @RequestParam("dateFrom") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime dateFrom,
                                                                      @RequestParam("dateTo") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime dateTo,
                                                                      @RequestParam(value = "onlySkipped") boolean onlySkipped,
                                                                      @PathVariable(value = "reportType") String reportType,
                                                                      @AuthenticationPrincipal UserBean userBean) throws NoDataException {
    AccountEntity account = accountService.findById(accountId).orElseThrow(() -> new NoDataException("Account not exist"));
    ZoneId userTimeZone = ZoneId.of(userBean.getUserTimeZone());
    DateTimeFormatter zoneTimeFormatter = DateTimeFormatter.ofPattern(ModelsConstants.PATTERN_TIME_ONLY_MINUTES).withZone(userTimeZone);
    CompletableFuture<List<ReportVoyagePointBean>> future = CompletableFuture.supplyAsync(() -> {
        try {
            return reportService.getVoyagePointData(
                    new ReportInfoBean(dateFrom, dateTo, account, userBean.getUserTimeZone(), zoneTimeFormatter), ids, reportType, onlySkipped);
        } catch (NoDataException e) {
            throw new RuntimeException(e);
        }
    }, executorService);

    try {
        List<ReportVoyagePointBean> result = future.get();
        return new ResponseEntity<>(result, HttpStatus.OK);
    } catch (InterruptedException | ExecutionException e) {
        throw new RuntimeException(e);
    } 
}

但是,当我调用 future.get() 时,它会卡住并且不返回任何内容,导致无限等待。如果我在没有 CompletableFuture 且具有相同参数的情况下调用 reportService.getVoyagePointData,它可以正常工作并返回所有数据。

我尝试过但没有帮助的事情:

  • 为循环中的每个 ID 调用 CompletableFuture,然后将它们加入 一份清单
  • 添加了具有不同初始化的 ExecutorService,例如 具有指定超时的fixedThreadPool或newCachedThreadPool
  • 添加了最后一个块,我在其中调用 executorService.shutdown()
  • 使用 Future 而不是 CompletableFuture

预先感谢您的帮助!

编辑: 我尝试过的 ExecutorService 的初始化:

private final ExecutorService executorService = Executors.newCachedThreadPool();
private final ExecutorService executorService = Executors.newFixedThreadPool(6);
//and using this config 
@Configuration
public class ExecutorConfig {
    @Bean
    public ExecutorService getExecutor() {
        return new ThreadPoolExecutor(1, 5, 4, TimeUnit.MINUTES,
                new ArrayBlockingQueue<>(50), Executors.defaultThreadFactory(), new RejectedExecutionHandlerImpl());
    }
}
java spring multithreading completable-future
1个回答
0
投票

解决了!

此错误的主要原因是我的实体是 CompletableFuture 内代码的一部分,并且这些实体的某些部分是延迟初始化的,它们需要连接到数据库才能获取数据。我通过创建一个 DTO 并在 CompletableFuture 上方初始化它来解决这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.