如果原始 ApiFuture / ListenableFuture 失败或取消,什么是 Futures.transform() lambda 参数
What is Futures.transform() lambda argument in case the original ApiFuture / ListenableFuture failed or cancelled
我有一个异步发送消息列表的方法。每次发送 returns ApiFuture<String>
(Guava 的 GCP 版本 ListenableFuture
)。我需要这个方法return一个Future<Boolean>
,所以我
- 为每个
ApiFuture<String>
创建一个列表依赖
- 使用
ApiFutures.transform
方法 将生成的ApiFuture<List<String>>
转换为Future<Boolean>
ApiFuture< List < String > > allSentFuture = ApiFutures.allAsList(futures);
return ApiFutures.transform(allSentFuture, val -> {
return true;
},
Executors.newCachedThreadPool()
);
我的问题是:如果一个或多个原始期货是 failed/cancelled,那么上述 lambda 的 val
参数的值是多少?在这种情况下甚至调用了 lambda 吗?
谢谢!
ApiFuture<V>
在类型 V
上形成一个 monad,并且 transform
将函数应用于类型 [=12] 的封装值=].如果 ApiFuture<V>
不包含 V
值,因为它失败或被取消,那么转换后的未来是相同的。
如果你想处理由于异常导致的失败,你可以使用 ApiFutures.catching()
来产生替代结果(例如 Boolean.FALSE
)。
如果你想把取消转化为成功的值,我相信你需要直接使用ApiFuture.addListener
,让监听器完成一个你return的SettableApiFuture
。然后监听器(当源未来被取消时将被调用)可以检查 isCancelled
来检测这种情况,或者可以捕获并处理 CancellationException
.
例如:
/**
* Adapt an iterable of {@link ApiFuture} instances into a single {@code ApiFuture}.
*/
static <T> ApiFuture<Boolean> adaptFutures(Iterable<ApiFuture<T>> futures) {
final SettableApiFuture<Boolean> result = SettableApiFuture.create();
final ApiFuture<List<T>> allFutures = ApiFutures.allAsList(futures);
allFutures.addListener(
() -> {
if (allFutures.isCancelled()) {
result.set(Boolean.FALSE);
return;
}
try {
allFutures.get();
result.set(Boolean.TRUE);
} catch (ExecutionException | InterruptedException ex) {
// Maybe log something here?
//
// Note that InterruptedException is actually impossible here
// because we're running in the listener callback, but the API
// still marks it as potentially thrown by .get() above.
//
// So if we reach here it means that the allAsList future failed.
result.set(Boolean.FALSE);
}
},
// Not normally safe, but we know our listener runs fast enough
// to run inline on the thread that completes the last future.
Runnable::run);
return result;
}
我有一个异步发送消息列表的方法。每次发送 returns ApiFuture<String>
(Guava 的 GCP 版本 ListenableFuture
)。我需要这个方法return一个Future<Boolean>
,所以我
- 为每个
ApiFuture<String>
创建一个列表依赖
- 使用
ApiFutures.transform
方法 将生成的
ApiFuture<List<String>>
转换为Future<Boolean>
ApiFuture< List < String > > allSentFuture = ApiFutures.allAsList(futures);
return ApiFutures.transform(allSentFuture, val -> {
return true;
},
Executors.newCachedThreadPool()
);
我的问题是:如果一个或多个原始期货是 failed/cancelled,那么上述 lambda 的 val
参数的值是多少?在这种情况下甚至调用了 lambda 吗?
谢谢!
ApiFuture<V>
在类型 V
上形成一个 monad,并且 transform
将函数应用于类型 [=12] 的封装值=].如果 ApiFuture<V>
不包含 V
值,因为它失败或被取消,那么转换后的未来是相同的。
如果你想处理由于异常导致的失败,你可以使用 ApiFutures.catching()
来产生替代结果(例如 Boolean.FALSE
)。
如果你想把取消转化为成功的值,我相信你需要直接使用ApiFuture.addListener
,让监听器完成一个你return的SettableApiFuture
。然后监听器(当源未来被取消时将被调用)可以检查 isCancelled
来检测这种情况,或者可以捕获并处理 CancellationException
.
例如:
/**
* Adapt an iterable of {@link ApiFuture} instances into a single {@code ApiFuture}.
*/
static <T> ApiFuture<Boolean> adaptFutures(Iterable<ApiFuture<T>> futures) {
final SettableApiFuture<Boolean> result = SettableApiFuture.create();
final ApiFuture<List<T>> allFutures = ApiFutures.allAsList(futures);
allFutures.addListener(
() -> {
if (allFutures.isCancelled()) {
result.set(Boolean.FALSE);
return;
}
try {
allFutures.get();
result.set(Boolean.TRUE);
} catch (ExecutionException | InterruptedException ex) {
// Maybe log something here?
//
// Note that InterruptedException is actually impossible here
// because we're running in the listener callback, but the API
// still marks it as potentially thrown by .get() above.
//
// So if we reach here it means that the allAsList future failed.
result.set(Boolean.FALSE);
}
},
// Not normally safe, but we know our listener runs fast enough
// to run inline on the thread that completes the last future.
Runnable::run);
return result;
}