AbstractQueuedSynchronizer(十三)——应用之Futures

1.CombinedFuture

通过allAsList和successfulAsList获得一个ListenableFuture,底层的实现是CombinedFuture。

return new CombinedFuture<V, List<V>>(
        futures, allMustSucceed, listenerExecutor,
        new FutureCombiner<V, List<V>>() {
          @Override
          public List<V> combine(List<Optional<V>> values) {
            List<V> result = Lists.newArrayList();
            for (Optional<V> element : values) {
              result.add(element != null ? element.orNull() : null);
            }
            return Collections.unmodifiableList(result);
          }
        });
CombinedFuture内部用ImmutableCollection保存了一份future的list,里面存储添加进来的future。

还有一个List<Optional<V>>保存每个future对应的value。

private static class CombinedFuture<V, C> extends AbstractFuture<C> {
    private static final Logger logger =
        Logger.getLogger(CombinedFuture.class.getName());

    ImmutableCollection<? extends ListenableFuture<? extends V>> futures;
    final boolean allMustSucceed;
    final AtomicInteger remaining;
    FutureCombiner<V, C> combiner;
    List<Optional<V>> values;
    final Object seenExceptionsLock = new Object();
    Set<Throwable> seenExceptions;

    CombinedFuture(
        ImmutableCollection<? extends ListenableFuture<? extends V>> futures,
        boolean allMustSucceed, Executor listenerExecutor,
        FutureCombiner<V, C> combiner) {
      this.futures = futures;
      this.allMustSucceed = allMustSucceed;
      this.remaining = new AtomicInteger(futures.size());
      this.combiner = combiner;
      this.values = Lists.newArrayListWithCapacity(futures.size());
      init(listenerExecutor);
    }
....
}

2.init方法

初始化操作,对每一个future都添加一个监听器listener,在监听器中进行setOneValue操作,即对List<Optional<V>>进行赋值操作。

在setOneValue的结尾判断还有多少个future的监听器没有被触发,如果所有的future的监听器都已经触发了的话,把所有future的值按照上面FutureCombiner内部类对combine方法的实现拼成一个list,并执行该CombinedFuture的set方法,触发该CombinedFuture的监听器。

3.allAsList和successfulAsList
如果这些future中有一个被设置了异常,那么再setOneValue中调用getUninterruptibly方法时,会抛出异常,被catch到之后会执行setExceptionAndMaybeLog方法。
/**
     * Fails this future with the given Throwable if {@link #allMustSucceed} is
     * true. Also, logs the throwable if it is an {@link Error} or if
     * {@link #allMustSucceed} is {@code true}, the throwable did not cause
     * this future to fail, and it is the first time we've seen that particular Throwable.
     */
    private void setExceptionAndMaybeLog(Throwable throwable) {
      boolean visibleFromOutputFuture = false;
      boolean firstTimeSeeingThisException = true;
      if (allMustSucceed) {
        // As soon as the first one fails, throw the exception up.
        // The result of all other inputs is then ignored.
        visibleFromOutputFuture = super.setException(throwable);

        synchronized (seenExceptionsLock) {
          if (seenExceptions == null) {
            seenExceptions = Sets.newHashSet();
          }
          firstTimeSeeingThisException = seenExceptions.add(throwable);
        }
      }

      if (throwable instanceof Error
          || (allMustSucceed && !visibleFromOutputFuture && firstTimeSeeingThisException)) {
        logger.log(Level.SEVERE, "input future failed.", throwable);
      }
    }
如果是allAsList,allMustSucceed是true,会通过调用父类的setException方法设置异常,同时触发外层ListenableFuture的监听器,不管其他内层future是否执行set方法。
如果是successfulAsList,allMustSucceed是false,不会通过setException设置异常,只会打印异常信息,并和正常执行了set的流程一样,把计数器减一,只是该内部future对应的value是初始化的null。
4.结构

这里有两个层次的ListenableFuture。

1.内层ListenableFuture

内层是所有的通过allAsList和successfulAsList方法添加进来的ListenableFuture,他们对应的监听器操作会把值设置到保存它们value的list中去,当所有的ListenableFuture的值都设置完毕(包括Exception),触发外层的ListenableFuture。内层ListenableFuture的具体实现就是传入的ListenableFuture的具体实现。

2.外层ListenableFuture

外层ListenableFuture的实现是CombinedFuture,可以为它添加监听器,内层所有ListenableFuture进行了setOneValue并触发外层减轻其的set操作的时候,就可以触发外层的监听器。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值