1、在OKHttp中需要一個(gè)隊(duì)列來(lái)保存不同的請(qǐng)求
/**
* 保存HttpConnection隊(duì)列
*/
private Deque<HttpConnection> mConnections = new ArrayDeque<>();
2、在每次請(qǐng)求前從線程池里檢查是否有超時(shí)的連接,將超時(shí)的連接從線程池移除
//在這里將連接放入線程池
public void put(HttpConnection httpConnection) {
if (!cleanupRunning) {
cleanupRunning = true;
EXECUTOR.execute(cleanupRunnable);
}
mConnections.add(httpConnection);
}
/**
* 清理線程
*/
private Runnable cleanupRunnable = () -> {
while(true) {
//等待再次檢查時(shí)間間隔
long waitTime = cleanup(System.currentTimeMillis());
if(waitTime == -1) {
return;
}
if(waitTime > 0) {
synchronized (ConnectionPool.this){
try {
ConnectionPool.this.wait(waitTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
//在這里清理超時(shí)請(qǐng)求
private long cleanup(long nowTime) {
//記錄最長(zhǎng)閑置時(shí)間
long longLastIdlTime = -1;
synchronized (this) {
//遍歷連接隊(duì)列
Iterator<HttpConnection> iterator = mConnections.iterator();
while (iterator.hasNext()) {
HttpConnection next = iterator.next();
//閑置時(shí)間
long idlDurationTime = nowTime - next.getLastUseTime();
if (idlDurationTime > keepAlive) {
iterator.remove();
next.close();
Log.d(TAG, "cleanup —> 超過(guò)閑置時(shí)間橘蜜,移出線程池");
continue;
}
//最長(zhǎng)的閑置時(shí)間
if (longLastIdlTime < idlDurationTime) {
longLastIdlTime = idlDurationTime;
}
}
//返回等待時(shí)間
if (longLastIdlTime >= 0) {
return keepAlive - longLastIdlTime;
}
//連接池沒(méi)有連接羡藐,可以退出
cleanupRunning = false;
return longLastIdlTime;
}
}
3、清理線程由線程池管理并將線程設(shè)為守護(hù)線程
/**
* 定義一個(gè)線程池,用來(lái)執(zhí)行清理線程
*/
private static final Executor EXECUTOR
= new ThreadPoolExecutor(
0, //最小并發(fā)線程數(shù)。
Integer.MAX_VALUE, //線程池中允許的最大線程數(shù)
60L, //當(dāng)線程的數(shù)目大于corePoolSize時(shí)栽燕,線程的最大存活時(shí)間。
TimeUnit.SECONDS, //時(shí)間單位
new SynchronousQueue<>(),//在執(zhí)行任務(wù)之前用于保存任務(wù)的隊(duì)列
r -> {//創(chuàng)建新的線程使用的工廠
Thread thread = new Thread(r, "ConnectionPool");
thread.setDaemon(true);
return thread;
});
4奈籽、線程池的復(fù)用,遍歷請(qǐng)求隊(duì)列的請(qǐng)求煮甥,判斷是否有相同的請(qǐng)求
/**
* 獲得可復(fù)用的連接池
*
* @param host
* @param port
* @return
*/
public HttpConnection get(String host, int port) {
Iterator<HttpConnection> iterator = mConnections.iterator();
while (iterator.hasNext()) {
HttpConnection next = iterator.next();
//判斷線程池里是否存在相同的請(qǐng)求地址
if (next.isSameAdress(host, port)) {
iterator.remove();
return next;
}
}
return null;
}
public boolean isSameAdress(String host, int port) {
if (TextUtils.isEmpty(host) || port < 0) {
throw new NullPointerException("Host OR Port maybe null point,Please Check it once again");
}
if (mSocket == null) {
return false;
}
return TextUtils.equals(host, mSocket.getInetAddress().getHostName()) && port == mSocket.getPort();
}