spa*_*pan 3 java concurrency java-8 completable-future
我试图从我CompletableFuture这样的列表中返回一个列表:
public List<Provider> get() {
CompletableFuture<List<Provider>> providersResponse = getSomeData();
return providersResponse.thenAccept((List<Provider> providers) -> {
return providers;
});
}
Run Code Online (Sandbox Code Playgroud)
它失败了"意外的返回类型.但是如何以异步方式返回结果?
你的目标存在根本矛盾.您只能拥有,get()返回一个完整的,可直接使用的列表或"以异步方式返回结果".
如果该方法List<Provider> get()应该返回一个List可以被调用者无限制地使用的方法,则它不能保持异步操作,因为操作必须在get()返回时完成.这可以像调用一样简单join(),等待完成并获得结果:
public List<Provider> get() {
CompletableFuture<List<Provider>> providersResponse = getSomeData();
return providersResponse.join();
}
Run Code Online (Sandbox Code Playgroud)
要不就
public List<Provider> get() {
return getSomeData().join();
}
Run Code Online (Sandbox Code Playgroud)
这有效地将潜在的异步操作getSomeData()转变为同步操作.
这个答案,使用
public List<Provider> get() {
List<Provider> providers = new ArrayList<>();
CompletableFuture<List<Provider>> providersResponse = getSomeData();
providersResponse.thenAccept(providers::addAll);
return providers;
}
Run Code Online (Sandbox Code Playgroud)
不等待操作完成,但ArrayList在调度addAll操作后返回一个新操作,该操作的执行完全不受此方法的控制.
这是一个异步操作,因此在get()返回时,List可能仍然为空,但稍后由任意线程更新.由于ArrayList不是线程安全的,感知状态不必是,空的或完成的,它可以是任意的中间状态,甚至不需要是一致的.在使用该代码时,要为奇怪的异常,不可能看的情况或其他惊喜做好准备.
当您使用线程安全List实现修复该代码时,您仍然会遇到以下问题:List在查询时返回的可能为空,并且在调用者控件之外的任意时间点填充.这是不可修复的,正如开头所说,这是想要异步操作但返回a的基本问题List.
这CompletableFuture已经是潜在异步操作的封装,因此如果您希望操作保持异步,只需返回CompletableFuture<List<Provider>>调用者,以便获得控制权.否则,如果您希望调用者接收List可以无限制使用的调用者,请在返回结果之前等待完成,例如通过join().
| 归档时间: |
|
| 查看次数: |
5748 次 |
| 最近记录: |