OKhttp的理解-RealConnectionPool

Posted 杨希锋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OKhttp的理解-RealConnectionPool相关的知识,希望对你有一定的参考价值。

RealConnectionPool

构造方案的参数:
maxIdleConnections: 最大连接数,默认为5。
keepAliveDuration: 存活时间,默认为5分钟。

public RealConnectionPool(int maxIdleConnections, long keepAliveDuration, TimeUnit timeUnit) {
    this.maxIdleConnections = maxIdleConnections; //默认为5
    this.keepAliveDurationNs = timeUnit.toNanos(keepAliveDuration); //默认为5分钟

    // Put a floor on the keep alive duration, otherwise cleanup will spin loop.
    if (keepAliveDuration <= 0) {
        throw new IllegalArgumentException("keepAliveDuration <= 0: " + keepAliveDuration);
    }
}

清理逻辑

采用一个线程池,核心线程数为0、最大线程数为Inter.MAX_VALUE, 空闲线程存活时间为60秒,等待队列为无缓冲队列(SynchronousQueue),即同一时间只能有一个任务在执行。清除流程为:
遍历connections队列,找到空闲最长时间的连接,如果最长空闲时间超过5分钟、或者空闲连接数量大于5,则从队列中删除该连接并关闭socket。

public final class RealConnectionPool {
    ...

    /**
     * @param now: 当前时间戳
     * @return: 分几种情况:
     *  > 0:距离下次清除的时间间隔;
     *  = 0: 已成功清除了最长空闲时间的连接;
     *  -1: connections队列为空,无空闲或正在使用的连接。
     */
    long cleanup(long now) {
        int inUseConnectionCount = 0;
        int idleConnectionCount = 0;
        RealConnection longestIdleConnection = null;
        long longestIdleDurationNs = Long.MIN_VALUE;

        // Find either a connection to evict, or the time that the next eviction is due.
        synchronized (this) {
            for (Iterator<RealConnection> i = connections.iterator(); i.hasNext(); ) {
                RealConnection connection = i.next();

                // If the connection is in use, keep searching.
                if (pruneAndGetAllocationCount(connection, now) > 0) {
                    inUseConnectionCount++;
                    continue;
                }

                idleConnectionCount++;

                // If the connection is ready to be evicted, we\'re done.
                long idleDurationNs = now - connection.idleAtNanos;
                if (idleDurationNs > longestIdleDurationNs) {
                    longestIdleDurationNs = idleDurationNs;
                    longestIdleConnection = connection;
                }
            }

            if (longestIdleDurationNs >= this.keepAliveDurationNs
                    || idleConnectionCount > this.maxIdleConnections) {
                // We\'ve found a connection to evict. Remove it from the list, then close it below (outside
                // of the synchronized block).
                connections.remove(longestIdleConnection);
            } else if (idleConnectionCount > 0) {
                // A connection will be ready to evict soon.
                return keepAliveDurationNs - longestIdleDurationNs;
            } else if (inUseConnectionCount > 0) {
                // All connections are in use. It\'ll be at least the keep alive duration \'til we run again.
                return keepAliveDurationNs;
            } else {
                // No connections, idle or in use.
                cleanupRunning = false;
                return -1;
            }
        }

        closeQuietly(longestIdleConnection.socket());

        // Cleanup again immediately.
        return 0;
    }
}

以上是关于OKhttp的理解-RealConnectionPool的主要内容,如果未能解决你的问题,请参考以下文章

三、深入理解OkHttp:连接处理-ConnectIntercepter

Android:OkHttp请求分发器 Dispatcher的理解和使用

Android:OkHttp同步和异步请求流程的理解和使用

深入理解OkHttp源码——提交请求

OKhttp的理解-RealConnectionPool

深入理解函数式编程一种基于Consumer和Builder的OkHttp函数式编程方法