本平台的文章更新会有延迟,大家可以关注微信公众号-顾林海,包括年底前会更新kotlin由浅入深系列教程,目前计划在微信公众号进行首发,如果大家想获取最新教程,请关注微信公众号,谢谢
OkHttp发送的同步或异步请求队列的状态会在dispatcher中进行管理,dispatcher的作用就是用于维护同步和异步请求的状态,内部维护一个线程池,用于执行相应的请求。
在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表示就绪状态的异步请求队列,如果当前的请求不满足某种条件时,当前的异步请求会进入就绪等待的异步请求队列中,当满足某种条件时,会从就绪等待的异步请求队列中取出异步请求,放入正在执行的异步请求队列中。
runningSyncCalls表示的正在执行的同步请求队列。
除了上面的三个队列,还有一个参数也是非常重要的,如下:
private @Nullable ExecutorService executorService;
executorService就是一个线程池对象,OkHttp的异步请求操作会放入这个线程池中。
OkHttp的异步请求在dispatcher中的一系列操作可以理解为生产者消费者模式,其中Dispatcher是生产者,它是运行在主线程中的,ExecutorService代表消费者池。
当同步和异步请求结束后,会调用dispatcher的finished方法,将当前的请求从队列中移除。
client.dispatcher().finished(this);
这段代码是在finally块中,也就是说,无论请求成不成功,还是出现异常,这段代码都会执行,保证了请求的整个生命周期从开始到销毁。
接下来,我们重新看看同步请求和异步请求在dispatcher中的操作。
1、同步请求会执行dispatcher的executed方法:
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
在executed方法中,只是将当前请求RealCall存入正在执行的同步请求队列中。
2、异步请求会执行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秒后进行关闭。
838794-506ddad529df4cd4.webp.jpg
搜索微信“顾林海”公众号,定期推送优质文章。
网友评论