我获得了一个执行gRPC调用的api( fnGrpc ),并返回一个ListenableFuture
,其解析为某个值 v (其执行情况)是固定的和不可修改的。)
我想提供一个帮助函数( fnHelper ):
对gRPC结果进行一些转换处理,并返回ListenableFuture
,解析为转换后的值 t1 。
处理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) {
// ...
}
如何在仍然让fnHelper返回ListenableFuture
并保持非阻止的情况下实现(2)?
我可以让 fnHelper 本身创建一个额外的线程,在其中我会在 fnGrpc 上调用.get()
,但还有另一种方法可以避免这个额外的线程吗?
答案 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
后缀的方法进行非阻塞处理。