首页 > 解决方案 > 可完成的未来因为返回类型不能按预期工作

问题描述

我在 Java 中有一个方法应该返回一个 CompletableFuture<Boolean<> ,当它应该为真时,我遇到了一些问题。我的方法如下:

@Override
    public CompletableFuture<Boolean> process(String name, Object data, Object message) {

        switch (name) {
            case ("first"):

                Map<String, Long> finalAmount = (Map<String, Long>) data;
                finalAmount.forEach((id, amount) -> {
                     event.retrieveEvent(id)
                            .thenCompose(config -> {
                                update(id, amount, config);
                                return CompletableFuture.completedFuture(true);
                            });
                });
        }
        return CompletableFuture.completedFuture(false);
    }

问题是我有一张地图,我必须遍历它并为每个值做一些事情。即使它总是以“CompletableFuture.completedFuture(true)”进入部分 - 最后,它总是进入最终的“return CompletableFuture.completedFuture(false)”并且它返回 false 而不是 true。

我能做什么,我应该如何重写我的方法,以便在地图元素完成后返回 true,并且对于每个元素,一切正常并且返回 true?

标签: javacompletable-future

解决方案


代码永远不会停下来等待 case 的结果case("first"),所以它会安排 aCompletableFuture来计算它并继续到return CompletableFuture.completedFuture(false);.

这是一种可能的解决方案:

@Override
public CompletableFuture<Boolean> process(String name, Object data, Object message) {
        switch (name) {
            case ("first"):
                CompletableFuture<Void> result = CompletableFuture.completedFuture( null );
                Map<String, Long> finalAmount = (Map<String, Long>) data;
                finalAmount.forEach((id, amount) -> {
                     result = result
                         .thenCompose(v -> event.retrieveEvent(id))
                         .thenAccept(config -> update(id, amount, config));
                });
                return result.thenApply(v -> Boolean.TRUE);
             
        }         
        return CompletableFuture.completedFuture(Boolean.FALSE);
    }

如果要并行运行所有任务,另一种解决方案是:

@Override
public CompletableFuture<Boolean> process(String name, Object data, Object message) {
        switch (name) {
            case ("first"):
                Map<String, Long> finalAmount = (Map<String, Long>) data;
                CompletableFuture<Void>[] futures = new CompletableFuture<>[finalAmount.size()];
                AtomicInteger index = new AtomicInteger();
                finalAmount.forEach((id, amount) -> {
                     futures[index.getAndIncrement()] = event
                         .retrieveEvent(id)
                         .thenAccept(config -> update(id, amount, config));
                });
                return CompletableFuture
                    .allOf(futures)
                    .thenApply(v -> Boolean.TRUE);
        }         
        return CompletableFuture.completedFuture(Boolean.FALSE);
    }

假设一切都是线程安全的。


推荐阅读