Java 如果原始ApiFuture/ListenableFuture失败或取消,Futures.transform()lambda参数是什么

Java 如果原始ApiFuture/ListenableFuture失败或取消,Futures.transform()lambda参数是什么,java,asynchronous,google-cloud-platform,guava,future,Java,Asynchronous,Google Cloud Platform,Guava,Future,我有一个异步发送消息列表的方法。每次发送都返回ApiFuture(Guava的GCP版本ListenableFuture)。我需要此方法返回一个Future,因此 在每个ApiFuture 使用ApiFutures.Transform方法将结果ApiFuture转换为Future apifurtureallsentfurture=apifurtures.allAsList(futures); 返回ApiFutures.transform(allSentFuture,val->{ 返回true;

我有一个异步发送消息列表的方法。每次发送都返回
ApiFuture
(Guava的GCP版本
ListenableFuture
)。我需要此方法返回一个
Future
,因此

  • 在每个
    ApiFuture
  • 使用
    ApiFutures.Transform
    方法将结果
    ApiFuture
    转换为
    Future

  • apifurture>allsentfurture=apifurtures.allAsList(futures);
    返回ApiFutures.transform(allSentFuture,val->{
    返回true;
    }, 
    Executors.newCachedThreadPool()
    );
    
    我的问题是:如果一个或多个原始期货失败/取消,上面lambda的
    val
    参数的值是多少?在这种情况下,lambda被调用了吗

    谢谢

    apifourt
    在类型
    V
    上形成一个单子,并且
    transform
    将函数应用于类型
    V
    的封装值。如果
    apifourture
    由于失败或取消而不包含
    V
    值,则转换后的未来是相同的

    如果要处理异常导致的故障,可以使用
    apifourtures.catching()
    生成替代结果(例如
    Boolean.FALSE

    如果您想将取消转换为成功的值,我相信您需要直接使用
    ApiFuture.addListener
    ,并让侦听器完成一个
    SettableApiFuture
    ,然后返回。然后监听器(在源未来被取消时将被调用)可以检查
    isCancelled
    来检测这种情况,或者可以捕获并处理
    取消异常

    例如:

    /**
     * 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;
    }
    
    /**
    *将{@link APIFURTURE}实例的iterable适配为单个{@code APIFURTURE}。
    */
    静态期货(可转换期货){
    最终SettableApiFuture结果=SettableApiFuture.create();
    最终ApiFuture allFutures=ApiFutures.allAsList(futures);
    allFutures.addListener(
    () -> {
    if(allFutures.isCancelled()){
    result.set(Boolean.FALSE);
    返回;
    }
    试一试{
    all futures.get();
    result.set(Boolean.TRUE);
    }捕获(ExecutionException | InterruptedException ex){
    //也许在这里写点什么?
    //
    //请注意,中断异常在这里实际上是不可能的
    //因为我们在侦听器回调中运行,但是API
    //仍然将其标记为可能由上面的.get()引发。
    //
    //因此,如果我们到达这里,这意味着所有人的未来都失败了。
    result.set(Boolean.FALSE);
    }
    },
    //通常不安全,但我们知道我们的听众跑得足够快
    //在最后一个将来完成的线程上内联运行。
    Runnable::run);
    返回结果;
    }
    
    它没有被调用。@CliveEvans如果调用方在最终结果上调用wait(),会发生什么?是否引发异常?
    /**
     * 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;
    }