直接从CompletableFuture.thenAccept返回值 [英] Return value directly from CompletableFuture.thenAccept

查看:684
本文介绍了直接从CompletableFuture.thenAccept返回值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图像这样从我的CompletableFuture返回列表:

I am trying to return a list from my CompletableFuture like this:

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?

推荐答案

您的目标存在根本矛盾.您只能使用get()返回完整的,直接可用的列表或以异步方式返回结果".

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".

如果方法List<Provider> get()应该返回一个List,调用方可以不受限制地使用它,则它不能保持异步操作,因为该操作必须在get()返回时完成.只需调用join()即可等待完成并获得结果:

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. This can be achieved as simple as calling join(), to wait for the completion and get the result:

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

或者只是

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

这有效地将getSomeData()的潜在异步操作转变为同步操作.

This effectively turns the potentially asynchronous operation of getSomeData() into a synchronous operation.

此答案,使用

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

不等待操作完成,而是在安排addAll操作之后返回新的ArrayList,其执行完全不受该方法的控制.

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.

这是一个异步操作,因此当get()返回时,List可能仍为空,但稍后会由任意线程进行更新.由于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. 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. Be prepared for strange exceptions, impossible-looking situations or other surprises when using that code.

使用线程安全的List实现修复该代码时,仍然存在以下问题:查询返回的List可能为空,并在调用者控制范围之外的任意时间填充.正如开头所说,这是无法解决的,这是需要异步操作但返回List的根本问题.

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. That’s not fixable, as said at the beginning, it’s the fundamental problem of wanting an asynchronous operation but returning a List.

CompletableFuture已经是潜在异步操作的封装,因此,如果您希望操作保持异步,只需将CompletableFuture<List<Provider>>返回给调用方,即可获得控制权.否则,如果您希望呼叫者收到一个List,可以不受限制地使用它,请等待完成,然后再返回结果,例如通过join().

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. Otherwise, if you want the caller to receive a List which can be used without restrictions, wait for the completion before returning the result, e.g. via join().

这篇关于直接从CompletableFuture.thenAccept返回值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆