简体   繁体   English

直接从CompletableFuture.thenAccept返回值

[英]Return value directly from CompletableFuture.thenAccept

I am trying to return a list from my CompletableFuture like this: 我试图从CompletableFuture返回一个列表,如下所示:

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

It fails with "unexpected return type though. How can I return the result in an async way? 它失败了“意外的返回类型。但是如何以异步方式返回结果?

There is a fundamental contradiction in your goal. 你的目标存在根本矛盾。 You can have only either, get() returning a complete, directly usable list or “return the result in an async way”. 您只能使用get()返回完整的,可直接使用的列表或“以异步方式返回结果”。

If the method List<Provider> get() is supposed to return a List which can be used by the caller without restrictions, it can't stay an asynchronous operation, as the operation must have been completed when get() returns. 如果方法List<Provider> get()应该返回一个可以由调用者无限制地使用的List ,则它不能保持异步操作,因为当get()返回时操作必须已经完成。 This can be achieved as simple as calling join() , to wait for the completion and get the result: 这可以像调用join()一样简单,等待完成并获得结果:

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

or just 要不就

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

This effectively turns the potentially asynchronous operation of getSomeData() into a synchronous operation. 这有效地将getSomeData()的潜在异步操作转换为同步操作。

This answer , using 这个答案 ,使用

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

does not wait for the completion of the operation, but returns a new ArrayList after scheduling an addAll operation, whose execution is entirely out of control of this method. 不等待操作完成,但在调度addAll操作后返回一个新的ArrayList ,该操作的执行完全不受此方法的控制。

This is an asynchronous operation, so when get() returns, the List might still be empty, but get updated at a later time by an arbitrary thread. 这是一个异步操作,因此当get()返回时, List可能仍然是空的,但稍后会被任意线程更新。 Since ArrayList is not thread safe, the perceived state doesn't have to be either, empty or completed, it may be an arbitrary in-between state, not even required to be consistent. 由于ArrayList不是线程安全的,因此感知状态不必是,空的或完成的,它可以是任意的中间状态,甚至不需要是一致的。 Be prepared for strange exceptions, impossible-looking situations or other surprises when using that code. 在使用该代码时,要为奇怪的异常,看起来不可能的情况或其他惊喜做好准备。

When you fix that code by using a thread safe List implementation, you still have the problem that the returned List might be empty when queried and get filled at an arbitrary point of time outside of the caller's control. 当您通过使用线程安全List实现来修复该代码时,仍然会遇到以下问题:返回的List在查询时可能为空,并在调用者控件之外的任意时间点填充。 That's not fixable, as said at the beginning, it's the fundamental problem of wanting an asynchronous operation but returning a List . 这是不可修复的,如开头所说,这是想要异步操作但返回List的基本问题。

The CompletableFuture is already an encapsulation of a potentially asynchronous operation, so if you want the operation to stay asynchronous, just return the CompletableFuture<List<Provider>> to the caller, to allow to gain control. CompletableFuture已经是潜在异步操作的封装,因此如果您希望操作保持异步,只需将CompletableFuture<List<Provider>>返回给调用者,以便获得控制权。 Otherwise, if you want the caller to receive a List which can be used without restrictions, wait for the completion before returning the result, eg via join() . 否则,如果您希望调用者接收可以无限制使用的List ,请在返回结果之前等待完成,例如通过join()

Try this: 试试这个:

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

Try this: 试试这个:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 从调用线程运行 CompletableFuture.thenAccept? - Running CompletableFuture.thenAccept from the calling thread? CompletableFuture.thenAccept确实可以阻止 - CompletableFuture.thenAccept can indeed block CompletableFuture.thenAccept中使用的垃圾回收对象的可用性 - Availability of objects for garbage collection used inside CompletableFuture.thenAccept CompletableFuture thenAccept 不起作用 - CompletableFuture thenAccept does not work 如何直接从 Uni 返回一个值<t>无需将其转换为 CompletableFuture</t> - how can one return a value directly from Uni<T> without converting that into a CompletableFuture 为什么CompletableFuture的thenAccept()没有在主线程上运行 - Why CompletableFuture 's thenAccept() not running on the main thread 调用使用 CompletableFuture 的 thenAccept() 的方法 - Invoking a method which uses CompletableFuture's thenAccept() `CompletableFuture.completedFuture ... thenAccept`是否等同于顺序处理? - is `CompletableFuture.completedFuture … thenAccept` equivalent to sequential processing? 如何在不阻塞的情况下从嵌套的 CompletableFuture 返回值? - How to return a value from a nested CompletableFuture without blocking? 如何使用CompletableFuture返回值 - How to return a value using CompletableFuture
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM