gpt4 book ai didi

java - 为什么okhttp程序不会卡在while(true)中?

转载 作者:行者123 更新时间:2023-12-01 17:51:43 26 4
gpt4 key购买 nike

最近在读OKHTTP的源码,发现RetryAndFollowUpInterceptor.java中有一个while(true)的回收。但是,程序没有堆叠在该位置或发生“应用程序未响应”。然后我附加了调试器并在该位置放置了一个断点,发现它正在主线程中运行。我不知道为什么程序运行完全正常。谁能帮助我?感谢stephenC的回答,但你可能不明白我的意思。在我的问题中,我的意思是为什么程序没有卡在主线程中的 while(true) 回收中。例如,如果 Activity 的 onCreate() 生命周期中有 while(true) 回收,则应用程序可能无法正常运行,只是停留在该位置并且无法响应触摸事件,这意味着应用程序没有响应(ANR)。回收将如何退出?以下为源码:

@Override
public Response intercept(Chain chain) throws IOException {
...
//This is the start of the recycle!Just recycle forever
while (true) {
if (canceled) {
streamAllocation.release();
throw new IOException("Canceled");
}

Response response;
boolean releaseConnection = true;
try {
response = realChain.proceed(request, streamAllocation, null, null);
releaseConnection = false;
} catch (RouteException e) {
// The attempt to connect via a route failed. The request will not have been sent.
if (!recover(e.getLastConnectException(), streamAllocation, false, request)) {
throw e.getFirstConnectException();
}
releaseConnection = false;
continue;
} catch (IOException e) {
// An attempt to communicate with a server failed. The request may have been sent.
boolean requestSendStarted = !(e instanceof ConnectionShutdownException);
if (!recover(e, streamAllocation, requestSendStarted, request)) throw e;
releaseConnection = false;
continue;
} finally {
// We're throwing an unchecked exception. Release any resources.
if (releaseConnection) {
streamAllocation.streamFailed(null);
streamAllocation.release();
}
...
}
}
}

最佳答案

如果你正在谈论这个:

    if (!recover(e.getLastConnectException(), streamAllocation, false, request)) {
throw e.getFirstConnectException();
}
releaseConnection = false;
continue;

IOException 的类似代码,recover(...) 调用测试以查看失败的请求是否可恢复。 (请参阅该方法以了解其实际含义。但条件之一是存在尚未尝试过的替代路线。)如果调用返回 true,则 intercept 方法将重试。如果它返回false,则重新抛出相关异常。

一般来说,类中的逻辑很复杂,但这是必须的。而且它显然确实有效。因此,也许您只需要阅读/研究更多上下文即可了解正在发生的事情。

请注意,使用调试器来跟踪这一点可能很困难,因为由于超时以不同的方式发生并改变了正常的控制流,行为很容易发生变化。考虑一下这种可能性...

<小时/>

更新

How will the recycle exit?

这称为循环,而不是回收。

正如我上面所解释的,如果 recover(...) 调用返回 false,您突出显示的特定循环路径将终止(通过重新抛出异常)。让我们看一下恢复

  private boolean recover(IOException e, boolean routeException, Request userRequest) {
streamAllocation.streamFailed(e);

// The application layer has forbidden retries.
if (!client.retryOnConnectionFailure()) return false;

// We can't send the request body again.
if (!routeException && userRequest.body() instanceof UnrepeatableRequestBody) return false;

// This exception is fatal.
if (!isRecoverable(e, routeException)) return false;

// No more routes to attempt.
if (!streamAllocation.hasMoreRoutes()) return false;

// For failure recovery, use the same route selector with a new connection.
return true;
}

第一个语句是对 StreamAllocation 对象进行一些清理。与此无关。

该方法的其余部分正在测试各种事情:

  • 应用层禁止重试,它表示不要重试。
  • 如果请求已发送且不是可重新发送的请求,则会提示不要重试。
  • 如果异常表明重试无法修复的错误,则表示不要重试。
  • 如果路线选择器没有更多路线可供尝试,则会表示不要重试。
  • 否则它会提示“重试”。下次调用 proceed 时,它将尝试路由选择器中的下一条路由。

请注意,最终它将耗尽可供尝试的替代路线。

关于java - 为什么okhttp程序不会卡在while(true)中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60784017/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com