OKHttp如何实现同步异步请求?
——客户端发出的同步/异步请求都会在dispatcher里面统一进行队列状态管理
到底什么是dispatcher?
——Dispatcher的主要作用就是维护请求的状态,并维护一个线程池,用于执行请求
Dispatcher对异步请求的处理逻辑远比处理同步请求的逻辑复杂。
总结起来,Dispatcher的作用:
1、分发同步或者异步请求;
2、处理并维护同步或者异步请求的状态,并维护线程池,用于执行请求的复用。
Dispatcher的操作都是在UI线程里面实现的。
关于Dispatcher我们关注的几个变量:
private int maxRequests = 64;//OKHttp允许的最大并发请求数量
private int maxRequestsPerHost = 5;//主机允许的最大并发请求数量
private Runnable idleCallback;
private ExecutorService executorService;// 异步请求要用到的线程池
/** Ready async calls in the order they'll be run——已加入队列准备就绪将要执行的异步请求**/
private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();
/** 异步请求要用到的队列:正在执行、还没有执行完成以及取消的异步请求队列*/
private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();
/** 同步请求要用到的队列:正在执行、还没有执行完成以及取消的同步请求队列*/
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
异步请求为什么要用到两个队列readyAsyncCalls和runningAsyncCalls?
——前面说了,Dispatcher的主要作用就是维护请求的状态,并维护一个线程池,用于执行请求。当我们有很多个请求要执行的时候,特别是请求的数量超过了线程池executorService中要求的数量的时候,有一部分请求将不会被立即执行,而是被缓存起来,这时,我们的请求的状态就分为两种:执行中的、准备就绪将要执行的,对于这两种不同状态的请求,我们肯定需要两个队列来存储,以便管理:
Deque< readyAsyncCalls >准备就绪将要执行、
Deque< runningAsyncCalls >正在执行的。
类似于生产者和消费者的关系:Dispatcher生产者、executorService消费者