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