AsyncHttpClient ListenableFuture源码流程解读

 更新时间:2023年12月18日 08:35:35   作者:codecraft  
这篇文章主要为大家介绍了AsyncHttpClient ListenableFuture源码流程解读,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

本文主要研究一下AsyncHttpClient的ListenableFuture

ListenableFuture

org/asynchttpclient/ListenableFuture.java

public interface ListenableFuture<V> extends Future<V> {
  /**
   * Terminate and if there is no exception, mark this Future as done and release the internal lock.
   */
  void done();
  /**
   * Abort the current processing, and propagate the {@link Throwable} to the {@link AsyncHandler} or {@link Future}
   *
   * @param t the exception
   */
  void abort(Throwable t);
  /**
   * Touch the current instance to prevent external service to times out.
   */
  void touch();
  /**
   * Adds a listener and executor to the ListenableFuture.
   * The listener will be {@linkplain java.util.concurrent.Executor#execute(Runnable) passed
   * to the executor} for execution when the {@code Future}'s computation is
   * {@linkplain Future#isDone() complete}.
   * <br>
   * Executor can be <code>null</code>, in that case executor will be executed
   * in the thread where completion happens.
   * <br>
   * There is no guaranteed ordering of execution of listeners, they may get
   * called in the order they were added and they may get called out of order,
   * but any listener added through this method is guaranteed to be called once
   * the computation is complete.
   *
   * @param listener the listener to run when the computation is complete.
   * @param exec     the executor to run the listener in.
   * @return this Future
   */
  ListenableFuture<V> addListener(Runnable listener, Executor exec);
  CompletableFuture<V> toCompletableFuture();
  //......
}
ListenableFuture继承了java.util.concurrent.Future,它定义了done、abort、touch、addListener、toCompletableFuture方法

CompletedFailure

org/asynchttpclient/ListenableFuture.java

class CompletedFailure<T> implements ListenableFuture<T> {
    private final ExecutionException e;
    public CompletedFailure(Throwable t) {
      e = new ExecutionException(t);
    }
    public CompletedFailure(String message, Throwable t) {
      e = new ExecutionException(message, t);
    }
    @Override
    public boolean cancel(boolean mayInterruptIfRunning) {
      return true;
    }
    @Override
    public boolean isCancelled() {
      return false;
    }
    @Override
    public boolean isDone() {
      return true;
    }
    @Override
    public T get() throws ExecutionException {
      throw e;
    }
    @Override
    public T get(long timeout, TimeUnit unit) throws ExecutionException {
      throw e;
    }
    @Override
    public void done() {
    }
    @Override
    public void abort(Throwable t) {
    }
    @Override
    public void touch() {
    }
    @Override
    public ListenableFuture<T> addListener(Runnable listener, Executor exec) {
      if (exec != null) {
        exec.execute(listener);
      } else {
        listener.run();
      }
      return this;
    }
    @Override
    public CompletableFuture<T> toCompletableFuture() {
      CompletableFuture<T> future = new CompletableFuture<>();
      future.completeExceptionally(e);
      return future;
    }
  }
CompletedFailure实现了ListenableFuture接口,其cancel方法返回true、isDone返回true

NettyResponseFuture

org/asynchttpclient/netty/NettyResponseFuture.java

public final class NettyResponseFuture<V> implements ListenableFuture<V> {
  private static final Logger LOGGER = LoggerFactory.getLogger(NettyResponseFuture.class);
  @SuppressWarnings("rawtypes")
  private static final AtomicIntegerFieldUpdater<NettyResponseFuture> REDIRECT_COUNT_UPDATER = AtomicIntegerFieldUpdater
          .newUpdater(NettyResponseFuture.class, "redirectCount");
  @SuppressWarnings("rawtypes")
  private static final AtomicIntegerFieldUpdater<NettyResponseFuture> CURRENT_RETRY_UPDATER = AtomicIntegerFieldUpdater
          .newUpdater(NettyResponseFuture.class, "currentRetry");
  @SuppressWarnings("rawtypes")
  private static final AtomicIntegerFieldUpdater<NettyResponseFuture> IS_DONE_FIELD = AtomicIntegerFieldUpdater
          .newUpdater(NettyResponseFuture.class, "isDone");
  @SuppressWarnings("rawtypes")
  private static final AtomicIntegerFieldUpdater<NettyResponseFuture> IS_CANCELLED_FIELD = AtomicIntegerFieldUpdater
          .newUpdater(NettyResponseFuture.class, "isCancelled");
  @SuppressWarnings("rawtypes")
  private static final AtomicIntegerFieldUpdater<NettyResponseFuture> IN_AUTH_FIELD = AtomicIntegerFieldUpdater
          .newUpdater(NettyResponseFuture.class, "inAuth");
  @SuppressWarnings("rawtypes")
  private static final AtomicIntegerFieldUpdater<NettyResponseFuture> IN_PROXY_AUTH_FIELD = AtomicIntegerFieldUpdater
          .newUpdater(NettyResponseFuture.class, "inProxyAuth");
  @SuppressWarnings("rawtypes")
  private static final AtomicIntegerFieldUpdater<NettyResponseFuture> CONTENT_PROCESSED_FIELD = AtomicIntegerFieldUpdater
          .newUpdater(NettyResponseFuture.class, "contentProcessed");
  @SuppressWarnings("rawtypes")
  private static final AtomicIntegerFieldUpdater<NettyResponseFuture> ON_THROWABLE_CALLED_FIELD = AtomicIntegerFieldUpdater
          .newUpdater(NettyResponseFuture.class, "onThrowableCalled");
  @SuppressWarnings("rawtypes")
  private static final AtomicReferenceFieldUpdater<NettyResponseFuture, TimeoutsHolder> TIMEOUTS_HOLDER_FIELD = AtomicReferenceFieldUpdater
          .newUpdater(NettyResponseFuture.class, TimeoutsHolder.class, "timeoutsHolder");
  @SuppressWarnings("rawtypes")
  private static final AtomicReferenceFieldUpdater<NettyResponseFuture, Object> PARTITION_KEY_LOCK_FIELD = AtomicReferenceFieldUpdater
          .newUpdater(NettyResponseFuture.class, Object.class, "partitionKeyLock");
  private final long start = unpreciseMillisTime();
  private final ChannelPoolPartitioning connectionPoolPartitioning;
  private final ConnectionSemaphore connectionSemaphore;
  private final ProxyServer proxyServer;
  private final int maxRetry;
  private final CompletableFuture<V> future = new CompletableFuture<>();          
          //......
  @Override
  public V get() throws InterruptedException, ExecutionException {
    return future.get();
  }
  @Override
  public V get(long l, TimeUnit tu) throws InterruptedException, TimeoutException, ExecutionException {
    return future.get(l, tu);
  }          
}
NettyResponseFuture实现了ListenableFuture接口

done

public final void done() {
    if (terminateAndExit())
      return;
    try {
      loadContent();
    } catch (ExecutionException ignored) {
    } catch (RuntimeException t) {
      future.completeExceptionally(t);
    } catch (Throwable t) {
      future.completeExceptionally(t);
      throw t;
    }
  }
  private boolean terminateAndExit() {
    releasePartitionKeyLock();
    cancelTimeouts();
    this.channel = null;
    this.reuseChannel = false;
    return IS_DONE_FIELD.getAndSet(this, 1) != 0 || isCancelled != 0;
  }  
private void loadContent() throws ExecutionException {
    if (future.isDone()) {
      try {
        future.get();
      } catch (InterruptedException e) {
        throw new RuntimeException("unreachable", e);
      }
    }
    // No more retry
    CURRENT_RETRY_UPDATER.set(this, maxRetry);
    if (CONTENT_PROCESSED_FIELD.getAndSet(this, 1) == 0) {
      try {
        future.complete(asyncHandler.onCompleted());
      } catch (Throwable ex) {
        if (ON_THROWABLE_CALLED_FIELD.getAndSet(this, 1) == 0) {
          try {
            try {
              asyncHandler.onThrowable(ex);
            } catch (Throwable t) {
              LOGGER.debug("asyncHandler.onThrowable", t);
            }
          } finally {
            cancelTimeouts();
          }
        }
        future.completeExceptionally(ex);
      }
    }
    future.getNow(null);
  }
done方法对于terminateAndExit返回true的直接返回,否则执行loadContent,它对于future.isDone()的执行future.get(),然后执行future.complete(asyncHandler.onCompleted())回调

abort

public final void abort(final Throwable t) {
    if (terminateAndExit())
      return;
    future.completeExceptionally(t);
    if (ON_THROWABLE_CALLED_FIELD.compareAndSet(this, 0, 1)) {
      try {
        asyncHandler.onThrowable(t);
      } catch (Throwable te) {
        LOGGER.debug("asyncHandler.onThrowable", te);
      }
    }
  }
abort方法也是对于terminateAndExit返回true的直接返回,否则执行future.completeExceptionally(t),然后触发asyncHandler.onThrowable(t)回调

touch

public void touch() {
    touch = unpreciseMillisTime();
  }
touch方法用当前时间戳更新touch属性

addListener

public ListenableFuture<V> addListener(Runnable listener, Executor exec) {
    if (exec == null) {
      exec = Runnable::run;
    }
    future.whenCompleteAsync((r, v) -> listener.run(), exec);
    return this;
  }
addListener方法会执行future.whenCompleteAsync((r, v) -> listener.run(), exec)

toCompletableFuture

public CompletableFuture<V> toCompletableFuture() {
    return future;
  }
toCompletableFuture方法直接返回future

newNettyResponseFuture

org/asynchttpclient/netty/request/NettyRequestSender.java

private <T> NettyResponseFuture<T> newNettyResponseFuture(Request request,
                                                            AsyncHandler<T> asyncHandler,
                                                            NettyRequest nettyRequest,
                                                            ProxyServer proxyServer) {
    NettyResponseFuture<T> future = new NettyResponseFuture<>(
            request,
            asyncHandler,
            nettyRequest,
            config.getMaxRequestRetry(),
            request.getChannelPoolPartitioning(),
            connectionSemaphore,
            proxyServer);
    String expectHeader = request.getHeaders().get(EXPECT);
    if (HttpHeaderValues.CONTINUE.contentEqualsIgnoreCase(expectHeader))
      future.setDontWriteBodyBecauseExpectContinue(true);
    return future;
  }
  private <T> ListenableFuture<T> sendRequestWithCertainForceConnect(Request request,
                                                                     AsyncHandler<T> asyncHandler,
                                                                     NettyResponseFuture<T> future,
                                                                     ProxyServer proxyServer,
                                                                     boolean performConnectRequest) {
    NettyResponseFuture<T> newFuture = newNettyRequestAndResponseFuture(request, asyncHandler, future, proxyServer,
            performConnectRequest);
    Channel channel = getOpenChannel(future, request, proxyServer, asyncHandler);
    return Channels.isChannelActive(channel)
            ? sendRequestWithOpenChannel(newFuture, asyncHandler, channel)
            : sendRequestWithNewChannel(request, proxyServer, newFuture, asyncHandler);
  }
NettyRequestSender的newNettyResponseFuture创建的是NettyResponseFuture;sendRequestWithCertainForceConnect则将NettyResponseFuture传递给sendRequestWithOpenChannel或者sendRequestWithNewChannel来发送请求

小结

AsyncHttpClient的ListenableFuture继承了java.util.concurrent.Future,它定义了done、abort、touch、addListener、toCompletableFuture方法;它有两个实现类,分别是CompletedFailure及NettyResponseFuture;NettyRequestSender的sendRequest方法将NettyResponseFuture传递给sendRequestWithOpenChannel或者sendRequestWithNewChannel来发送请求。

以上就是聊聊AsyncHttpClient的ListenableFuture的详细内容,更多关于AsyncHttpClient的ListenableFuture的资料请关注脚本之家其它相关文章!

以上就是AsyncHttpClient ListenableFuture源码流程解读的详细内容,更多关于AsyncHttpClient ListenableFuture的资料请关注脚本之家其它相关文章!

相关文章

  • 给你的MyBatis-Plus装上批量插入的翅膀(推荐)

    给你的MyBatis-Plus装上批量插入的翅膀(推荐)

    这篇文章主要介绍了给你的MyBatis-Plus装上批量插入的翅膀,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-09-09
  • SpringBoot自动配置实现的详细步骤

    SpringBoot自动配置实现的详细步骤

    这篇文章主要为大家介绍了SpringBoot自动配置实现详细的过程步骤,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • 分模块构建Maven工程的方法步骤

    分模块构建Maven工程的方法步骤

    这篇文章主要介绍了分模块构建Maven工程的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • JAVA实现数字大写金额转换的方法

    JAVA实现数字大写金额转换的方法

    这篇文章主要介绍了JAVA实现数字大写金额转换的方法,涉及java针对字符串与数组的遍历与转换相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • Java中定时任务的全方位场景实现思路分析

    Java中定时任务的全方位场景实现思路分析

    在开发过程中,根据需求和业务的不同经常会有很多场景需要用到不同特性的定时任务,本文将针对这些场景,提供不同的一个实现思路,感兴趣的小伙伴快跟随小编一起学习一下吧
    2023-12-12
  • Java实现正则匹配 “1234567” 这个字符串出现四次或四次以上

    Java实现正则匹配 “1234567” 这个字符串出现四次或四次以上

    文章介绍了如何在Java中使用正则表达式匹配一个字符串四次或四次以上的出现,首先创建正则表达式,然后使用Pattern和Matcher类进行匹配和计数,通过示例代码展示了如何实现这一功能,并解释了匹配的整体次数和精确出现次数的逻辑,感兴趣的朋友一起看看吧
    2025-02-02
  • 一文教你搞懂SpringBoot自定义拦截器的思路

    一文教你搞懂SpringBoot自定义拦截器的思路

    在开发中,都离不开拦截器的使用,比如说在开发登录功能时,实现权限管理功能时等,这篇文章主要带大家使用SpringBoot梳理自定义拦截器的思路,需要的可以参考一下
    2023-08-08
  • 详解Java中的reactive stream协议

    详解Java中的reactive stream协议

    Stream大家应该都很熟悉了,java8中为所有的集合类都引入了Stream的概念。优雅的链式操作,流式处理逻辑,相信用过的人都会爱不释手。本文将详细介绍Java中的reactive stream协议。
    2021-06-06
  • 如何用Maven开发Spring Boot项目详解

    如何用Maven开发Spring Boot项目详解

    SpringBoot是一个集成Spring框架优点的开源后台开发框架,自动化配置和内嵌容器等特性减少了配置工作量,使得开发者可以更加专注于业务逻辑,这篇文章主要介绍了如何用Maven开发Spring Boot项目,需要的朋友可以参考下
    2024-09-09
  • SpringBoot配置文件中数据库密码加密两种方案(推荐)

    SpringBoot配置文件中数据库密码加密两种方案(推荐)

    SpringBoot项目经常将连接数据库的密码明文放在配置文件里,安全性就比较低一些,尤其在一些企业对安全性要求很高,因此我们就考虑如何对密码进行加密,文中给大家介绍加密的两种方式,感兴趣的朋友一起看看吧
    2019-10-10

最新评论