Return 值直接来自 CompletableFuture.thenAccept
Return value directly from CompletableFuture.thenAccept
我正在尝试 return 我的 CompletableFuture
中的列表,如下所示:
public List<Provider> get() {
CompletableFuture<List<Provider>> providersResponse = getSomeData();
return providersResponse.thenAccept((List<Provider> providers) -> {
return providers;
});
}
它失败了,但出现了“意外的 return 类型。我怎样才能 return 以异步方式得到结果?
试试这个:
public List<Provider> get() {
List<Provider> providers = Collections.synchronizedList(new ArrayList<>());
CompletableFuture<List<Provider>> providersResponse = getSomeData();
providersResponse.thenAccept(providers::addAll);
return providers;
}
试试这个:
public List<Provider> get() {
return getSomeData().get();
}
您的目标存在根本矛盾。您只能拥有 get()
return 一个完整的、直接可用的列表或“return 异步方式的结果”。
如果方法 List<Provider> get()
应该 return 一个 List
可以被调用者无限制地使用,它不能保持异步操作,因为操作必须已在 get()
return 秒时完成。这个可以很简单的实现,调用join()
,等待完成,得到结果:
public List<Provider> get() {
CompletableFuture<List<Provider>> providersResponse = getSomeData();
return providersResponse.join();
}
或者只是
public List<Provider> get() {
return getSomeData().join();
}
这有效地将 getSomeData()
的潜在异步操作转变为同步操作。
,使用
public List<Provider> get() {
List<Provider> providers = new ArrayList<>();
CompletableFuture<List<Provider>> providersResponse = getSomeData();
providersResponse.thenAccept(providers::addAll);
return providers;
}
不等待操作完成,而是 return 在调度 addAll
操作之后新的 ArrayList
,其执行完全不受此方法的控制。
这是一个异步操作,所以当 get()
returns 时,List
可能仍然是空的,但稍后会被任意线程更新。由于 ArrayList
不是线程安全的,因此感知状态不必是空的或已完成的,它可以是任意的中间状态,甚至不需要保持一致。使用该代码时,请为奇怪的异常、看似不可能的情况或其他意外情况做好准备。
当您使用线程安全 List
实现修复该代码时,您仍然会遇到 returned List
在查询时可能为空并在调用者控制之外的任意时间点。这是不可修复的,如开头所说,这是想要异步操作但 returning List
.
的根本问题
CompletableFuture
已经是一个潜在异步操作的封装,所以如果你想让操作保持异步,只需 return 将 CompletableFuture<List<Provider>>
给调用者,以允许获得控制权。否则,如果您希望调用者收到可以不受限制地使用的 List
,请在 returning 结果之前等待完成,例如通过 join()
.
我正在尝试 return 我的 CompletableFuture
中的列表,如下所示:
public List<Provider> get() {
CompletableFuture<List<Provider>> providersResponse = getSomeData();
return providersResponse.thenAccept((List<Provider> providers) -> {
return providers;
});
}
它失败了,但出现了“意外的 return 类型。我怎样才能 return 以异步方式得到结果?
试试这个:
public List<Provider> get() {
List<Provider> providers = Collections.synchronizedList(new ArrayList<>());
CompletableFuture<List<Provider>> providersResponse = getSomeData();
providersResponse.thenAccept(providers::addAll);
return providers;
}
试试这个:
public List<Provider> get() {
return getSomeData().get();
}
您的目标存在根本矛盾。您只能拥有 get()
return 一个完整的、直接可用的列表或“return 异步方式的结果”。
如果方法 List<Provider> get()
应该 return 一个 List
可以被调用者无限制地使用,它不能保持异步操作,因为操作必须已在 get()
return 秒时完成。这个可以很简单的实现,调用join()
,等待完成,得到结果:
public List<Provider> get() {
CompletableFuture<List<Provider>> providersResponse = getSomeData();
return providersResponse.join();
}
或者只是
public List<Provider> get() {
return getSomeData().join();
}
这有效地将 getSomeData()
的潜在异步操作转变为同步操作。
public List<Provider> get() {
List<Provider> providers = new ArrayList<>();
CompletableFuture<List<Provider>> providersResponse = getSomeData();
providersResponse.thenAccept(providers::addAll);
return providers;
}
不等待操作完成,而是 return 在调度 addAll
操作之后新的 ArrayList
,其执行完全不受此方法的控制。
这是一个异步操作,所以当 get()
returns 时,List
可能仍然是空的,但稍后会被任意线程更新。由于 ArrayList
不是线程安全的,因此感知状态不必是空的或已完成的,它可以是任意的中间状态,甚至不需要保持一致。使用该代码时,请为奇怪的异常、看似不可能的情况或其他意外情况做好准备。
当您使用线程安全 List
实现修复该代码时,您仍然会遇到 returned List
在查询时可能为空并在调用者控制之外的任意时间点。这是不可修复的,如开头所说,这是想要异步操作但 returning List
.
CompletableFuture
已经是一个潜在异步操作的封装,所以如果你想让操作保持异步,只需 return 将 CompletableFuture<List<Provider>>
给调用者,以允许获得控制权。否则,如果您希望调用者收到可以不受限制地使用的 List
,请在 returning 结果之前等待完成,例如通过 join()
.