是否可以使用 Guava 链接异步调用?

Posted

技术标签:

【中文标题】是否可以使用 Guava 链接异步调用?【英文标题】:Is it possible to chain async calls using Guava? 【发布时间】:2012-01-01 18:37:32 【问题描述】:

我想链接异步休息服务调用并在它们完成时有一个回调。

可以用番石榴做吗?

【问题讨论】:

一点点更新,您可以使用专为此目的设计的FluentFuture。它为您提供了来自Futures 的最重要的方法,但使用了流畅的 API。您可以使用静态工厂from 启动链。 【参考方案1】:

Futures.chain 在版本 12.0 中被删除。将ListenableFutures 链接在一起的新方法是通过Futures.transform 方法。

https://github.com/google/guava/wiki/ListenableFutureExplained#application

来自 Guava 最新的 javadoc(撰写本文时16.0.1)。

ListenableFuture<RowKey> rowKeyFuture = indexService.lookUp(query);
AsyncFunction<RowKey, QueryResult> queryFunction =
   new AsyncFunction<RowKey, QueryResult>() 
   public ListenableFuture<QueryResult> apply(RowKey rowKey) 
      return dataService.read(rowKey);
   
;
ListenableFuture<QueryResult> queryFuture = transform(rowKeyFuture, queryFunction);

【讨论】:

我正在使用 Futures.transform,但我得到的代码块嵌套了 12 层。有没有办法将其线性化? @Sridhar-Sarnobat 当然,只是“放松”它。创建最里面的未来,将其组合成一个新的变量,等等。 @maaartinus hmmmm 我不确定我明白了。响应正文中的示例会有所帮助 @Sridhar-Sarnobat 这不是我的答案,我不确定它是否是一个好的编辑。我的意思是这样的:ListenableFuture f1 = ...; ListenableFuture f2 = transform(f1, fun1, executor); ListenableFuture f3 = transform(f2, fun2, executor); ...。它与 int x1 = ...; int x2 = fun1(x1); int x3 = fun2(x2); ... 这样的函数调用链并没有什么不同。您无需计算价值,而是计算期货。您可以通过在需要之前声明这些部件来避免任何嵌套。 +++ 你可以使用“提取局部变量”来做到这一点,但直接这样做更简单明了。 哦,我明白了。它只是提取局部变量。通常我喜欢像你说的那样内联一次性变量。我希望可能会有一个转换,需要一个平面的期货列表,但我想不会。【参考方案2】:

您可以使用Futures.chain 链接ListenableFutures:

final ListeningExecutorService service1 = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(16));
final ListeningExecutorService service2 = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(16));

ListenableFuture<String> service1result = service1.submit(new Callable<String>() 
    @Override
    public String call() throws Exception 
        return "service1result";
    
);

ListenableFuture<String> service2result = Futures.chain(service1result, new Function<String, ListenableFuture<String>>() 
    @Override
    public ListenableFuture<String> apply(final @Nullable String input) 
        return service2.submit(new Callable<String>() 
            @Override
            public String call() throws Exception 
                return Joiner.on(" -> ").join(input, "service2result");
            
        );
    
);

System.out.format("Result: %s\r\n", service2result.get());

上面代码在终端的输出:

> run-main training.Training
[info] Compiling 1 Java source to /home/remeniuk/projects/guava-training/target/scala-2.9.1/classes...
[info] Running training.Training 
Result: service1result -> service2result

【讨论】:

值得注意的是,Futures.chain 不再可用。另一种方法是使用Futures.transform

以上是关于是否可以使用 Guava 链接异步调用?的主要内容,如果未能解决你的问题,请参考以下文章

从Java Future到Guava ListenableFuture实现异步调用

从Java future 到 Guava ListenableFuture实现异步调用

链式异步函数

dubbo同步调用异步调用和是否返回结果源码分析和实例

是否可以在非异步方法中调用等待方法? [复制]

是否总是需要使用 await 调用异步函数?