gpt4 book ai didi

java - CompletableFuture 执行中出现意外的空值

转载 作者:行者123 更新时间:2023-12-02 09:13:28 25 4
gpt4 key购买 nike

我需要运行大量 REST 调用并保存结果。为了加快速度,我想并行进行。以下代码通常可以工作,但有时我会在结果列表中得到空值(始终位于第一个位置)。知道为什么会发生这种情况吗?

第二个问题。有更好的方法来完成此任务(并行 REST 调用)吗?

List<Result> result = new ArrayList<>();
CompletableFuture.allOf(ids.stream()
.map(id -> asyncRestService.fetchResult(id)
.exceptionally(e -> {
log.error("error id: " + id, e);
return new Result();
})
.thenAccept(result::add))
.toArray(CompletableFuture<?>[]::new)
).join();

log.debug("Result: " + result);
@Async
public CompletableFuture<Result> fetchResult(String id) {
Result result = new Result();
// adding something to result
return CompletableFuture.completedFuture(result);
}

最佳答案

我不确定这是否是代码的主要问题,但它肯定会导致您上面描述的行为。

您正在访问result以非线程安全的方式,如 ArrayList是一种不同步的数据结构。

假设两个线程同时完成它们正在处理的请求。当 lambda 传递到 CompletableFuture#thenAccept(Consumer<? super T>) 时由完成 future 的线程执行,ArrayList#(E)函数也可能被并行调用。这可能会导致结果不一致,快速浏览一下ArrayList#add(E)的源代码显示:

public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}

element类型为Object[] ,此操作不是线程安全的,可能会导致数据争用。 size 也是如此。 。即使我们假设每次更改为 size (和 element )可用于任何其他线程,但这仍然不能像 size++ 那样工作。尽管 size 是一个非原子操作s 数据类型(读取和写入 int are atomic 类型的变量,但 size++ 由多个读取和写入操作组成)。

关于java - CompletableFuture 执行中出现意外的空值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59209595/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com