我正在尝试从我的 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/