引用CompletableFuture中的一个字段,它也可以是CompletableFuture:java

时间:2015-09-02 10:29:54

标签: java java-8 completable-future

我正在调用一个返回CompletableFuture的服务。

输出结构如下。

Class Output {
    public String name;
    public Integer age;
}

我想打电话给服务,并希望继续我的执行,直到名字出现。

类似的东西,

CompletableFuture<Output> futureOutput = makeServiceCall(input);
String name = futureOutput.get().name;
processName(name); // which will do some costly operations and make use of the name at the end. 

在上面的方法中,我需要等到我的futureOutput准备就绪,即使我以后只需要它。

我寻找类似下面的方法。

CompletableFuture<Output> futureOutput = makeServiceCall(input);
CompletableFuture<String> futureName = futureOutput.get().name; // This is wrong, but can we create a reference in a similar way?
processName(futureName); // which will do some costly operations and make use of the name at the end. 

我可以将processName的签名从String更改为CompletableFuture<String>而不是CompletableFuture<Output>,因为Output对此没有任何意义方法。

有什么建议的方法来获得未来的参考,这是另一个未来的领域。

2 个答案:

答案 0 :(得分:6)

只需使用CompletableFuture.thenApplyAsync

来自JavaDoc:

  

返回一个新的CompletionStage,当这个阶段正常完成时,使用这个阶段的默认异步执行工具执行,该阶段的结果作为所提供函数的参数。

在您的示例中(TprocessName方法的返回类型):

CompletableFuture<Output> future = makeServiceCall(input);
CompletableFuture<T> result = future.thenApplyAsync(o -> processName(o.name));

现在,当makeServiceCall CompletableFuture完成时,会生成另一个CompletableFuture以将异步调用包装到processName - 这会创建一个异步管道。

根据您的目的,您可以改为使用CompletableFuture.thenAcceptAsync,例如,如果processName没有返回有用的结果:

CompletableFuture<Output> future = makeServiceCall(input);
CompletableFuture<Void> result = future.thenAcceptAsync(o -> processName(o.name));

如果此处理未完成,您可能还需要进行错误处理,这可以通过CompletableFuture.exceptionally来完成。如果处理管道以Exception终止,则会添加一个回调函数。

通过完整的示例,您可以:

makeServiceCall(input)
    .thenApplyAsync(Output::getName)
    .thenAcceptAsync(this::processName)
    .exceptionally(e -> {
        //log the error
        System.out.printf("Oops - %s%n", e);
        //return some useful default value
        return ProcessingResult.SUCCESSFUL;
    });

这个管道(虽然有点做作 - 没有必要得到名称异步)是完全异步的。无需阻止任何点创建任务的Thread;任务将成功完成或将调用失败处理程序。

答案 1 :(得分:0)

您可以将结果提供给新的完成阶段,例如:

CompletableFuture<Output> futureOutput = makeServiceCall(input);
futureOutput.thenAcceptAsync(output -> processName(output.name));

(如果要在操作完成之前阻止,请使用thenAccept