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

时间:2018-02-28 19:04:11

标签: java asynchronous java-8 guava future

我获得了一个执行gRPC调用的api( fnGrpc ),并返回一个ListenableFuture,其解析为某个值 v (其执行情况)是固定的和不可修改的。)

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

  1. 对gRPC结果进行一些转换处理,并返回ListenableFuture,解析为转换后的值 t1

  2. 处理gRPC调用失败,并返回其他值 t2 ,而不是让 fnHelper 的来电者看到ExecutionException

  3. 我可以使用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) {
      // ...
    }
    

    如何在仍然让fnHelper返回ListenableFuture并保持非阻止的情况下实现(2)?

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

1 个答案:

答案 0 :(得分:2)

我不是Guava的专家,但似乎你可以使用相同的Futures实用程序类,特别是方法catchingAsync来执行此操作,您可以在其中传递返回的函数ListenableFuture具有后备值(t2):

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 后缀的方法进行非阻塞处理。