在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);
}为什么我们有两个超时?
1. timeout as param
2. responseTimeoutInMs第二个超时正在伤害我们,因为调用即使在超时到期后也不会出现。它不断递归地再次调用get()。
一旦命中responseTimeoutInMs,连接是否会关闭?我们正在尝试将其设置为低于超时。
发布于 2013-11-07 04:04:49
我假设你指的是我在网络中找到的方法:
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;
}你可以认为这个类在几个方面是错误的。第一个直接引起注意的错误是使用System.currentTimeMillis()而不是System.nanoTime()。System.currentTimeMillis()指的是计算机系统时钟,它可以在程序执行期间进行调整,因此可以来回跳转。处理超时的代码应该使用System.nanoTime(),它给出一个与程序执行无关的值,独立于实际时钟。
responseTimeoutInMs似乎意味着连接超时,但即使在作为参数值传递的timeout过期时使用它也违反了Future约定。正确的行为应该是让get方法超时,即使Future表示的任务可能仍在运行。
但是递归地调用get方法是一个双重错误。递归不仅是危险的,因为较小的超时值可能导致StackOverflowError;再次将相同的timeout传递给自身意味着无限推迟超时,因为每次重新调用都会将该值视为相对于当前时间。
有趣的是,即使方法到了超时的时候,它也会将TimeoutException包装在一个ExecutionException中,向调用者报告一个完全错误的语义。
我不相信你会在stackoverflow上找到一个人可以解释这个实现背后的原理,如果有的话。您必须直接询问该代码的支持者/作者。
发布于 2016-01-08 20:20:04
不要使用JDK提供程序,它已经损坏,并将在AHC2中删除。使用Netty提供程序,并升级到最新版本。
https://stackoverflow.com/questions/13623995
复制相似问题