okhttp的網絡請求是基於socket請求,面不是原始的HttpConnection來操作的,但是Socket是很耗性能的,爲什麼Okhttp性能好速度快,是因爲他有做網絡請求緩存,還有一個就是他有一個連接池
連接池:主要目的就是把閒置一定時間的連接給中斷.簡單原理就是,創建一個線程池去做清理任務,這裏是無限循環.
每當發現閒置時間超過設置的時間,就會把這個Socket連接給關閉.
還有一個就是每次發起一次請求的時候,他會去連接池裏面找是否已經存在該連接,有的就複用.
這裏我自己手寫一個跟Okhttp類式的連接池 涉及到三個類
1: ConnectionPool2 這個是用來添加和獲取請求連接對象
2:HttpConnection2 這個是連接對象
3:UserConnection2Pool 這個是連接池使用類
上面三個類中,最主要的還是ConnectionPool2這個類,
首先有幾個成員變量
/**
* 檢查機制
* 每格一分鐘,就去檢查裏面連接是否可用,不可用,移除
*/
private long keepAlive;
private boolean cleanRunnableFlag;//是否啓動了清理任務
//保存網絡請求的隊列
private Deque<HttpConnection2> mHttpConnection2Deque = new ArrayDeque<>();
每當我們進行一個網絡連接的時候,就會先判斷隊裏裏面是否有,沒有就創建並將連接對象添加到隊裏裏,所有就有put和get方法
/**
* 添加連接對象,到連接池裏
*/
public synchronized void putConnection(HttpConnection2 httpConnection2) {
//一旦Put,就要檢查要去清理
if (!cleanRunnableFlag) {
cleanRunnableFlag = true;
mExecutor.execute(cleanRunnable);
}
mHttpConnection2Deque.add(httpConnection2);
}
/**
* 獲取連接對象,
*/
public HttpConnection2 getConnection(String host, int port) {
Iterator<HttpConnection2> iterator = mHttpConnection2Deque.iterator();
while (iterator.hasNext()) {
HttpConnection2 httpConnection2 = iterator.next();
if (httpConnection2.itConnectionAction(host, port)) {
//找到了
Log.e("ConnectionPool2","找到了連接,複用一下");
iterator.remove();
return httpConnection2;
}
}
return null;
}
其實連接池最主要的還是怎麼清理請求任務,下面代碼
/**
* 開啓一個線程,專門去檢查連接池裏面的(連接對象),無限循環
*/
private Runnable cleanRunnable = new Runnable() {
@Override
public void run() {
while (true) {
long nextCleanTime = clean(System.currentTimeMillis());
if (nextCleanTime == -1) {
cleanRunnableFlag = false;
return;
}
if (nextCleanTime > 0) {
//待一段時間再去清理
synchronized (ConnectionPool2.this) {
try {
ConnectionPool2.this.wait(nextCleanTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
};
/**
* 清理對象
*
* @param currentTimeMillis 當前時間
*/
private long clean(long currentTimeMillis) {
long idleRocordSave = -1;
Iterator<HttpConnection2> iterator = mHttpConnection2Deque.iterator();
while (iterator.hasNext()) {
HttpConnection2 httpConnection2 = iterator.next();
//我們添加的連接對象,超過了最大保持時間,移除連接對象
long idleTime = currentTimeMillis - httpConnection2.lastUseTime;
if (idleTime > keepAlive) {//大於最大的保持時間,將連接對象remove
Log.e("ConnectionPool2","已經超過時間了,移除socket連接");
iterator.remove();
httpConnection2.closeSocket();
continue;
}
//獲得到最長的閒置時間,看連接閒置的最大值
if (idleRocordSave < idleTime) {
idleRocordSave = idleTime;
}
}
if (idleRocordSave >= 0) {
return keepAlive - idleRocordSave;
}
return idleRocordSave;
}
所以,當時間過了設置的閒置時間就會將走
httpConnection2.closeSocket();這個方法也就是下面這些代碼
public void closeSocket() {
if (mSocket != null) {
try {
mSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
這就實現了請求的複用和長連接的關閉,達到了節省服務器的壓力.
OKhttp的連接池在哪裏創建和在哪裏使用
創建:當我們用builder創建OKHttpClient的時候這個時候就會創建一個連接池
哪裏使用上了
RetryAndFollowUpInterceptor重試攔截器的intercept方法中,當創建一個StreamAllocation