ListenableFuture链是否可以处理内部ExecutionException?

问题描述 投票:2回答:1

我提供了一个执行gRPC调用的api(fnGrpc)并返回一个解析为某个值v的ListenableFuture(其实现是固定且不可修改的)。

我想提供一个辅助函数(fnHelper):

  1. 对gRPC结果进行一些转换处理,并返回一个解析为转换值t1的ListenableFuture
  2. 处理gRPC调用的失败,并返回一些其他值t2,而不是让fnHelper的调用者看到ExecutionException

我可以通过使用Futures.transform()来解决(1):

package myHelper;

ListenableFuture<T> fnHelper() {
  return Futures.transform(fnGrpc(), new Function<V, T>() {
    @Override
    public T apply(V v) {
      T t1 = f(v);
      return t1;
    }
  });
} 

和来电者:

package myApp;

// ...

try {
  T t = fnHelper().get();
} catch (ExecutionException | InterruptedException ex) {
  // ...
}

我怎样才能实现(2)同时仍然让fnHelper返回ListenableFuture并保持非阻塞状态?

我可以让fnHelper自己创建一个额外的线程,我会在fnGrpc上调用.get(),但还有另一种方法可以避免这个额外的线程吗?

java asynchronous java-8 guava future
1个回答
2
投票

我不是Guava的专家,但似乎你可以使用相同的Futures实用程序类,特别是catchingAsync方法,在那里你可以传递一个函数,返回带有回退值的ListenableFuturet2):

ListenableFuture<Integer> faultTolerantFuture = Futures.catchingAsync(originalFuture,
                       Exception.class, x -> immediateFuture(t2), executor);

然后,您应该能够使用transform方法进行链接,该方法进行转换:

ListenableFuture<T> fnHelper() {
    return Futures.catching(Futures.transform(fnGrpc(), new Function<V, T>() {
        @Override
        public T apply(V v) {
            T t1 = f(v);
            return t1;
        }
    }),
    Exception.class, x -> immediateFuture(t2));
}

注意:在最后一个片段中,我使用catching而不是catchingAsync来与您问题中的代码保持一致,并且我没有指定执行程序。您可能需要使用带有Async后缀的方法进行非阻塞处理。

© www.soinside.com 2019 - 2024. All rights reserved.