直接从 CompletableFuture.thenAccept 返回值

2023-11-21

我正在尝试从我的列表中返回一个列表CompletableFuture像这样:

public List<Provider> get() {
    CompletableFuture<List<Provider>> providersResponse = getSomeData();
    return providersResponse.thenAccept((List<Provider> providers) -> {
        return providers;
    });
}

它失败并显示“意外的返回类型。如何以异步方式返回结果?


你的目标存在根本的矛盾。你只能拥有其中一个,get()返回一个完整的、可直接使用的列表或“以异步方式返回结果”。

如果方法List<Provider> get()应该返回一个List调用者可以不受限制地使用它,它不能保持异步操作,因为该操作必须在以下时间完成:get()返回。这可以通过简单的调用来实现join(),等待完成并得到结果:

public List<Provider> get() {
    CompletableFuture<List<Provider>> providersResponse = getSomeData();
    return providersResponse.join();
}

or just

public List<Provider> get() {
    return getSomeData().join();
}

这有效地改变了潜在的异步操作getSomeData()进入同步操作。

这个答案, using

public List<Provider> get() {
    List<Provider> providers = new ArrayList<>();
    CompletableFuture<List<Provider>> providersResponse = getSomeData();
    providersResponse.thenAccept(providers::addAll);
    return providers;
}

不等待操作完成,而是返回一个新的ArrayList安排后addAll操作,其执行完全不受此方法的控制。

这是一个异步操作,所以当get()返回,则List可能仍然是空的,但稍后会被任意线程更新。自从ArrayList不是线程安全的,感知的状态不必是空的或已完成的,它可以是任意的中间状态,甚至不需要一致。使用该代码时,请为奇怪的异常、看似不可能的情况或其他意外做好准备。

当您使用线程安全修复该代码时List实施,你仍然有返回的问题List查询时可能为空,并在调用者控制之外的任意时间点被填充。这是无法修复的,正如一开始所说,这是想要异步操作但返回一个的根本问题List.

The CompletableFuture已经是对潜在异步操作的封装,因此如果您希望操作保持异步,只需返回CompletableFuture<List<Provider>>给调用者,以允许获得控制权。否则,如果您希望呼叫者收到List可以不受限制地使用,等待完成后再返回结果,例如通过join().

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

直接从 CompletableFuture.thenAccept 返回值 的相关文章

随机推荐