当前位置: 首页 > 知识库问答 >
问题:

在递归调用中收集可完成的未来结果

韦熙云
2023-03-14

我有以下代码,即从返回CompletableFuture的web API获取给定时间间隔的报告。如果超过了返回报告的行数,时间间隔将被分成两半,并为两半调用API。这将递归重复,直到行数满足条件。

我想得到完全未来

我的代码在不需要进行间隔拆分时运行正常。如果需要递归调用,它将只返回空列表,递归调用将在稍后异步执行。

 protected CompletableFuture<List<APIResult<String>>> generateDomainReport(
        ExtendedDomainConfiguration domain,
        ZonedDateTime chunkStartDate,
        ZonedDateTime chunkEndDate,
        List<APIResult<String>> result) {

    CompletableFuture<APIResult<String>> response = runReport(domain.getDomainName(), chunkStartDate, chunkEndDate);
    return response.thenApply(report -> {
        // in case that count of report rows hit the limit, split timeWindow into two half,
        // calculate middle date and run report for both intervals: <startDate, middleDate>; <middleDate, endDate>
        if (isReportMaxRowCountReached(report.getContent(), domain.getMaxReportRowCount())) {
            LOGGER.warn(String.format(
                    "Report limit row counts was reached. " +
                            "Splitting window <%s, %s> into 2 parts and rerunning report",
                    chunkStartDate, chunkEndDate));
            Duration timeWindow = Duration.between(chunkStartDate, chunkEndDate);
            ZonedDateTime chunkMiddleDate = chunkEndDate.minus(Duration.ofSeconds(timeWindow.getSeconds() / 2));
            // recursively repeat until count of returned rows is under the limit
            generateDomainReport(domain, chunkStartDate, chunkMiddleDate, result);
            generateDomainReport(domain, chunkMiddleDate, chunkEndDate, result);
        } else {
            result.add(report);
        }
        return result;
    });
}

我也尝试过使用类似的东西,但没用:

response
.thenAccept(r -> generateDomainReport(domain, chunkStartDate, chunkMiddleDate, result))
.thenAccept(r -> generateDomainReport(domain, chunkMiddleDate, chunkEndDate, result));

如果我知道自己做错了什么,我会心存感激。谢谢

共有1个答案

皇甫琛
2023-03-14

我将我的原始代码转换成这样的东西,它似乎正在工作:

protected CompletableFuture<List<APIResult<String>>> generateDomainReport(
            ExtendedDomainConfiguration domain,
            ZonedDateTime chunkStartDate,
            ZonedDateTime chunkEndDate) {

        CompletableFuture<APIResult<String>> response = runReport(domain.getDomainName(), chunkStartDate, chunkEndDate);
        return response.thenApplyAsync(report -> {
            // in case that count of report rows hit the limit, split timeWindow into two half,
            // calculate middle date and run report for both intervals: <startDate, middleDate>; <middleDate, endDate>
            if (isReportMaxRowCountReached(report.getContent(), domain.getMaxReportRowCount())) {
                LOGGER.warn(String.format(
                        "CSV report limit row counts was reached. " +
                                "Splitting window <%s, %s> into 2 parts and rerunning report",
                        chunkStartDate, chunkEndDate));
                Duration timeWindow = Duration.between(chunkStartDate, chunkEndDate);
                ZonedDateTime chunkMiddleDate = chunkEndDate.minus(Duration.ofSeconds(timeWindow.getSeconds() / 2));
                // recursively repeat until count of returned rows is under the limit
                return generateDomainReport(domain, chunkStartDate, chunkMiddleDate)
                        .thenCombineAsync(generateDomainReport(domain, chunkMiddleDate, chunkEndDate),
                                (result1, result2) -> {
                                    List<APIResult<String>> result = new ArrayList<>(result1.size() + result2.size());
                                    result.addAll(result1);
                                    result.addAll(result2);
                                    return result;
                                }).join();
            } else {
                return List.of(report);
            }
        });
    }
 类似资料:
  • 我正在尝试将方法的调用/结果链接到下一个调用。我得到了编译时错误方法,因为if无法从前一次调用中获得objB的引用。 如何将上一次调用的结果传递给下一个链?我是不是完全误解了这个过程?

  • 问题内容: 我在JSON数据类型(Postgres 9.3)下以Postgres存储了JSON文档,我需要递归地收集树下的键名。 例如,给定此JSON树 我想提取类似[file1,file2,file3,file3,package1,package2,package3,package4]的内容 基本上只列出了可用于文本搜索索引的键。 我知道我可以使用以下方法在最外面的对象上列出键 而且我知道可以使

  • 我基于java的CompletableFuture构建了一个任务链,它可能非常长。我的问题是CompletableFuture中的每一个任务都是一个内部类,它包含对源CompletableFuture的引用,因此不可能对已完成的CompletableForture进行垃圾收集。有没有办法避免内存泄漏? 这是一段可用于重现此错误的代码:

  • 我要做的是异步计算树结构的深度,我将有树的第一层,我想启动一个异步线程来分别计算每个节点的深度。 在计算过程中,树中显然可能有一个分叉,在这一点上,我想踢一个额外的线程来计算那个分支。 我已经得到了这个工作,但我需要做一些整理逻辑,当所有这些未来完成。但我对这一过程中产生的额外的可完成的未来感到困扰。 我会用什么方法来保存所有开始的CompletableFutures+那些动态创建的,并且在执行任

  • 如果我有一个(或多个)尚未启动,并且在该方法上有几个,方法。 垃圾收集器会移除所有这些吗? 如果在该链的末尾有一个< code > join()/< code > get() 也许我们需要更多关于连接上下文的信息()。 这种连接是线程中的最后一个命令,并且没有副作用。那么在这种情况下,线程仍然是活动的吗?- Java线程垃圾收集与否 无论如何,这是一个好主意,如果我确信(也许在尝试捕获中),那么将

  • 我有一个名为Source的类,它有lazy val isValid来做一些需要时间的网络检查。我让它返回Future[Boolean],这样它就不会阻塞主线程: 现在,我想检查几个来源并丢弃无效的来源。 下面是一些伪代码: 我在想一些方法,可以将从isValid返回的Future[Boolean]转换为其他将来,在验证检查完成后,可以使用整个源对象进行解析。 最好的方法是什么?