2

在 AsyncHttpClient JDKFuture.get()

 public V  [More ...] get(long timeout, TimeUnit unit)  {
        V content = null;
        try {
            if (innerFuture != null) {
                content = innerFuture.get(timeout, unit);
            }
        } catch (TimeoutException t) {
            if (!contentProcessed.get() && timeout != -1 && 
              ((System.currentTimeMillis() -   touch.get()) <= responseTimeoutInMs)) {
                return get(timeout, unit);
            }

为什么我们有 2 次超时?

  1. timeout as param
  2. responseTimeoutInMs

第二次超时伤害了我们,因为即使在超时到期后呼叫也不会出现。它不断递归地再次调用 get()。

一旦 responseTimeoutInMs 被击中,连接会关闭吗?我们正在尝试将其设置为低于超时。

4

2 回答 2

3

我假设您指的是我在网上找到的方法:

public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
    V content = null;
    try {
        if (innerFuture != null) {
            content = innerFuture.get(timeout, unit);
        }
    } catch (TimeoutException t) {
        if (!contentProcessed.get() && timeout != -1 && ((System.currentTimeMillis() - touch.get()) <= responseTimeoutInMs)) {
            return get(timeout, unit);
        }

        if (exception.get() == null) {
            timedOut.set(true);
            throw new ExecutionException(new TimeoutException(String.format("No response received after %s", responseTimeoutInMs)));
        }
    } catch (CancellationException ce) {
    }

    if (exception.get() != null) {
        throw new ExecutionException(exception.get());
    }
    return content;
}

你可以认为这个类在几个方面是错误的。直接引起注意的第一个错误是使用 ofSystem.currentTimeMillis()而不是System.nanoTime()System.currentTimeMillis()指计算机系统时钟,在程序执行过程中可以调整,因此可以来回跳动。处理超时的代码应该使用System.nanoTime()它给出一个相对于程序执行的值,该值独立于现实世界的时钟。

responseTimeoutInMs似乎意味着连接超时,但即使timeout传递的参数值已过期,使用它也是违反Future合同的。正确的行为是让get方法超时,即使由 代表的任务Future可能仍在运行。

但是get递归调用该方法是一个双重错误。递归不仅是危险的,因为小的超时值可能会导致StackOverflowError; 再次将相同的值传递timeout给自身意味着无限延迟超时,因为每次重新调用都会将该值视为相对于当前时间。

有趣的是,即使方法到了超时点,它也会在TimeoutException内部包装一个ExecutionException向调用者报告完全错误的语义。

我不相信您会在 stackoverflow 上找到可以解释此实现背后的基本原理的人(如果有的话)。您必须直接询问该代码的支持者/作者。

于 2013-11-06T20:04:49.390 回答
0

不要使用 JDK 提供程序,它已损坏并在 AHC 2 中被删除。使用 Netty 并升级到现代版本。

于 2016-01-08T12:20:03.697 回答