java - 直接从 CompletableFuture.thenAccept 返回值

标签 java concurrency java-8 completable-future

我正在尝试从我的 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();
}

或者只是

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

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

This answer , 使用

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 的根本问题.

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

关于java - 直接从 CompletableFuture.thenAccept 返回值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43489281/

相关文章:

JavaFX 缩放打印弄乱了我的打印机

java - 计数事件并测试 rxJava

multithreading - 使用 HT 在一个 Core 上执行的线程之间的数据交换将使用什么?

Java 并发性 - 最好是拥有带锁的线程列表或带请求列表的线程?

java8 流和状态

java - 带数组构造函数的引用方法

java - 我可以计算计算机中的图像被查看了多少次并将计数数存储在java文件或cpp文件中?

Java : JFrame Issue with Print Statement

git 并行 pull 多个 Remote

java - 用索引迭代 IntStream