这里的具体就是放到线程池里的运行了。(以下内容为拓展) ExecutorService的创建方式如下:所有线程池最终都是通过这个方法来创建的。
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
BlockingQueue workQueue,ThreadFactory threadFactory,
RejectedExecutionHandler handler)
corePoolSize :核心线程数,一旦创建将不会再释放。如果创建的线程数还没有达到指定的核心线程数量,将会继续创建新的核心线程,直到达到最大核心线程数后,核心线程数将不在增加;如果没有空闲的核心线程,同时又未达到最大线程数,则将继续创建非核心线程;如果核心线程数等于最大线程数,则当核心线程都处于激活状态时,任务将被挂起,等待空闲线程来执行。
maximumPoolSize :最大线程数,允许创建的最大线程数量。如果最大线程数等于核心线程数,则无法创建非核心线程;如果非核心线程处于空闲时,超过设置的空闲时间,则将被回收,释放占用的资源。
keepAliveTime : 也就是当线程空闲时,所允许保存的最大时间,超过这个时间,线程将被释放销毁,但只针对于非核心线程。
unit : 时间单位,TimeUnit.SECONDS等。
workQueue : 任务队列,存储暂时无法执行的任务,等待空闲线程来执行任务。
threadFactory : 线程工程,用于创建线程。
handler : 当线程边界和队列容量已经达到最大时,用于处理阻塞时的程序
可以明显的看到创建时使用的队列为SynchronousQueue:它内部没有容器(可以去拓展一下,本文就不写了)
4.进入到下一个代码区execute():@Override protected void execute() {
boolean signalledCallback = false;
try {
//处理请求的地方
Response response = getResponseWithInterceptorChain();
if (retryAndFollowUpInterceptor.isCanceled()) {
signalledCallback = true;
responseCallback.onFailure(RealCall.this, new IOException(“Canceled”));
} else {
signalledCallback = true;
//回调将结果返回调用者
responseCallback.onResponse(RealCall.this, response);
}
} catch (IOException e) {
if (signalledCallback) {
// Do not signal the callback twice!
Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
} else {
eventListener.callFailed(RealCall.this, e);
//如果发生异常产生错误回调
responseCallback.onFailure(RealCall.this, e);
}
} finally {
//维护,执行完之后,调用dispatcher中的finish函数
client.dispatcher().finished(this);
}
}
5.可以明显的看到处理请求的为getResponseWithInterceptorChain()方法//责任链模式的设计
//(从一些维度来优化,如用户流量,响应速度,减少服务器承受的压力)
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List interceptors = new ArrayList<>();
//这一个是用来加自己的拦截器
interceptors.addAll(client.interceptors());
//下面是通用的
interceptors.add(retryAndFollowUpInterceptor);
interceptors.add(new BridgeInterceptor(client.cookieJar()));
interceptors.add(new CacheInterceptor(client.internalCache()));
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(forWebSocket));
//满足情况就继续往下走,不满足就返回。
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
return chain.proceed(originalRequest);
}
这个方法里面通过拦截器组成的责任链,依次经过用户自定义普通拦截器、重试拦截器、桥接拦截器、缓存拦截器、 连接拦截器和用户自定义网络拦截器以及访问服务器拦截器等拦截处理过程来获取到一个响应并交给用户。
各个拦截器的作用:
interceptors:用户自定义拦截器(根据具体业务决定)
retryAndFollowUpInterceptor:负责失败重试以及重定向
BridgeInterceptor:请求时,对必要的 Header 进行一些添加,接收响应时,移除必要的 Header
CacheInterceptor:负责读取缓存直接返回(根据请求的信息和缓存的响应的信息来判断是否存在缓存可用)、更新缓存
ConnectInterceptor:负责和服务器建立连接。
6.回到第四步维护,调用dispatcher中的finish函数private void finished(Deque calls, T call, boolean promoteCalls) {
int runningCallsCount;
Runnable idleCallback;
synchronized (this) {
//将队列中的元素删除,如果没有这个元素会抛出异常
if (!calls.remove(call)) throw new AssertionError(“Call wasn’t in-flight!”);
if (promoteCalls) promoteCalls();
runningCallsCount = running
CallsCount();
idleCallback = this.idleCallback;
}
//如果队列没有在执行的线程且idle线程不为空则执行。 可以看出每个线程结束完都会检查一遍是不是
//要执行空闲线程
if (runningCallsCount == 0 && idleCallback != null) {
idleCallback.run();
}
}
7.最后看看promoteCalls()方法;private void promoteCalls() {
if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.
for (Iterator i = readyAsyncCalls.iterator(); i.hasNext(); ) {
AsyncCall call = i.next();
if (runningCallsForHost(call) < maxRequestsPerHost) {
i.remove();
runningAsyncCalls.add(call);
//回到第三步
executorService().execute(call);
}
if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
}
}
此方法内容如下:
1.首先会判断当前正在运行的异步请求的数量是否超过他的最大数量,如果超过了就返回了就不要再做其他 *** 作了。
2.如果还能进行异步请求,就表示我们这个空闲还有余额,会直接返回。
3.接着会循环遍历这个等待的执行队列。
4.然通过next迭代器去获取到AsyncCall实例。
5.接着判断所有的运行的主机是否小于最大的限制,这是一个最大的前提条件。将call从等待队列中移到正在执行的请求队列当中,先移除,然后再把它添加到正在执行的异步请求队列当中。最后会开启一个线程池去执行请求(回到文中第三步)。
总结
===================================================================
OkHttp 内部的请求流程:使用 OkHttp 会在请求的时候初始化一个 Call 的实例,然后执行它的 execute()方法或 enqueue()方法,内部最后都会执行到getResponseWithInterceptorChain()方法,这个方法里面通过拦截器组成的责任链,依次经过用户自定义普通拦截器、重试拦截器、桥接拦截器、缓存拦截器、 连接拦截器和用户自定义网络拦截器以及访问服务器拦截器等拦截处理过程来获取到一个响应并交给用户。
下面给大家分享一份份《Android网络传输与数据存储优化》,富含8个模块,不仅有详细的底层原理解析,还有专门的项目实践案例及优化方案。
1. 网络优化的三个要点1.1 多维
1.2 精准
1.3 监控
…
2. 网络优化的两个维度2.1 流量维度
2.1.1 区分类型
2.1.2 监控异常
2.1.3 上报日志
2.2 质量维度
2.3 网络优化的两个误区
…
3.三个线下测试工具 4、周期长4.1 不能中断流程
4.2 关闭加载d窗
…
5.线上监控的三个要点5.1 服务端监控
5.2 客户端监控
5.3 异常监控
…
6. 三个线上监控方案6.1 OkHttp 事件监听器
6.1.1 自定义事件监听器
6.1.2 自定义 GlideModule
6.1.3 OkHttp 最大并发请求数
6.1.4 区分前后台流量
6.2 NetworkStatsManager
6.2.1 流量优化的三个要点
6.2.2 NetworkStatsManager 基本用法
6.3 TrafficStats
…
7.三个流量优化方案7.1 数据缓存
7.2 数据压缩
7.3 图片压缩
3b07.png)
6. 三个线上监控方案6.1 OkHttp 事件监听器
6.1.1 自定义事件监听器
6.1.2 自定义 GlideModule
6.1.3 OkHttp 最大并发请求数
6.1.4 区分前后台流量
6.2 NetworkStatsManager
6.2.1 流量优化的三个要点
6.2.2 NetworkStatsManager 基本用法
6.3 TrafficStats
…
7.三个流量优化方案7.1 数据缓存
7.2 数据压缩
7.3 图片压缩
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)