目錄
Okhttp3使用及解析:https://mp.csdn.net/postedit/83339916
okhttp系統攔截器:https://mp.csdn.net/postedit/83536609
Okhttp的連接池ConnectionPool:https://mp.csdn.net/postedit/83650740
Okhttp將客戶端和服務端之間通信的鏈接抽象成Connection類,而ConnectionPool就是管理這些鏈接的複用而出現的,作用就是在一定時間內可以複用Connection。
下面分析源碼:
1.get()方法
@Nullable
RealConnection get(Address address, StreamAllocation streamAllocation, Route route) {
assert (Thread.holdsLock(this));
//遍歷連接池connections
for (RealConnection connection : connections) {
//isEligible判斷是否可用
if (connection.isEligible(address, route)) {
//acquire獲取連接池
streamAllocation.acquire(connection, true);
return connection;
}
}
return null;
}
看看acquire():
public void acquire(RealConnection connection, boolean reportedAcquired) {
assert (Thread.holdsLock(connectionPool));
if (this.connection != null) throw new IllegalStateException();
//將連接池中獲取的RealConnection賦值
this.connection = connection;
this.reportedAcquired = reportedAcquired;
//將弱引用的StreamAllocation存入集合allocations
connection.allocations.add(new StreamAllocationReference(this, callStackTrace));
}
集合allocations存儲的多個StreamAllocation,方便後期通過size大小的判斷一個網絡鏈接的負載量是否超過最大值。
總結:每次的http請求會在重定向攔截器中創建StreamAllocation,且StreamAllocation的弱引用會被添加至泛型爲RealConnection的集合中,後面可通過集合大小判斷鏈接是否超過負載。同時,也提供在一定時間內連接池複用鏈接。
2.put()
void put(RealConnection connection) {
assert (Thread.holdsLock(this));
//線程池異步回收connection
if (!cleanupRunning) {
cleanupRunning = true;
executor.execute(cleanupRunnable);
}
//connection存入隊列
connections.add(connection);
}
題外話:看看cleanupRunnable回收的流程:
private final Runnable cleanupRunnable = new Runnable() {
@Override public void run() {
while (true) {
//計算下一次清理的時間
//gc的標記算法,存StreamAllocation弱引用的集合,遍歷發現爲空,則remove
long waitNanos = cleanup(System.nanoTime());
if (waitNanos == -1) return;
if (waitNanos > 0) {
long waitMillis = waitNanos / 1000000L;
waitNanos -= (waitMillis * 1000000L);
synchronized (ConnectionPool.this) {
try {
//等待時間,去執行下次清理
ConnectionPool.this.wait(waitMillis, (int) waitNanos);
} catch (InterruptedException ignored) {
}}}}}};