本平台的文章更新会有延迟,你们能够关注微信公众号-顾林海,包括年末前会更新kotlin由浅入深系列教程,目前计划在微信公众号进行首发,若是你们想获取最新教程,请关注微信公众号,谢谢java
OkHttp发送的同步或异步请求队列的状态会在dispatcher中进行管理,dispatcher的做用就是用于维护同步和异步请求的状态,内部维护一个线程池,用于执行相应的请求。web
在dispatcher内部维护着三个队列,这三个队列以下:微信
private final Deque<RealCall.AsyncCall> readyAsyncCalls = new ArrayDeque<>();
private final Deque<RealCall.AsyncCall> runningAsyncCalls = new ArrayDeque<>();
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
复制代码
runningAsyncCalls表示的是正在执行的异步请求队列。异步
readyAsyncCalls表示就绪状态的异步请求队列,若是当前的请求不知足某种条件时,当前的异步请求会进入就绪等待的异步请求队列中,当知足某种条件时,会从就绪等待的异步请求队列中取出异步请求,放入正在执行的异步请求队列中。this
runningSyncCalls表示的正在执行的同步请求队列。spa
除了上面的三个队列,还有一个参数也是很是重要的,以下:线程
private @Nullable ExecutorService executorService;
复制代码
executorService就是一个线程池对象,OkHttp的异步请求操做会放入这个线程池中。code
OkHttp的异步请求在dispatcher中的一系列操做能够理解为生产者消费者模式,其中Dispatcher是生产者,它是运行在主线程中的,ExecutorService表明消费者池。cdn
当同步和异步请求结束后,会调用dispatcher的finished方法,将当前的请求从队列中移除。对象
client.dispatcher().finished(this);
复制代码
这段代码是在finally块中,也就是说,不管请求成不成功,仍是出现异常,这段代码都会执行,保证了请求的整个生命周期从开始到销毁。
接下来,咱们从新看看同步请求和异步请求在dispatcher中的操做。
一、同步请求会执行dispatcher的executed方法:
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
复制代码
在executed方法中,只是将当前请求RealCall存入正在执行的同步请求队列中。
二、异步请求会执行dispatcher的enqueue方法;
private int maxRequests = 64;
private int maxRequestsPerHost = 5;
synchronized void enqueue(RealCall.AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
//第一步
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
//第二步
readyAsyncCalls.add(call);
}
}
复制代码
上一节在讲解异步请求时已经解释过了,这里直接复制过来:在enqueue方法前使用了synchronized关键字进行修饰,也就是为这个方法加了个同步锁,继续往下看第一步,先是判断当前异步请求总数是否小于设定的最大请求数(默认是64),以及正在运行的每一个主机请求数是否小于设定的主机最大请求数(默认是5),若是知足这两个条件,就会把传递进来的AsyncCall对象添加到正在运行的异步请求队列中,而后经过线程池执行这个请求。若是知足不了上面的两个条件就会走第二步,将AsyncCall对象存入readyAsyncCalls队列中,这个readyAsyncCalls就是用来存放等待请求的一个异步队列。
其中线程池的建立和获取代码以下:
public synchronized ExecutorService executorService() {
if (executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
复制代码
建立线程池时,第一个参数表示核心线程数,设置为0,当线程池空闲一段时间后,就会将线程池中的全部线程进行销毁;第二个参数表示最大线程数,设置为整型的最大值,具体多少线程数仍是受限OkHttp中的maxRequests这个参数;第三个参数表示当咱们的线程数大于核心线程数的时候,多余的空闲线程存活的最大时间为60秒,结合第一个核心线程数为0,也就是说OkHttp中的线程在工做完毕后,会在60秒后进行关闭。
搜索微信“顾林海”公众号,按期推送优质文章。