返回

OkHttpClient同步异步请求分析和Dispatcher任务调度

Android







## OkHttpClient同步异步请求分析

OkHttpClient提供了两种请求方式:同步请求和异步请求。

### 同步请求

调用Callexecute()方法发送同步请求,发送请求后,就会进入阻塞状态,直到收到响应。

```java
Call call = client.newCall(request);
Response response = call.execute();

异步请求

调用Call的enqueue()方法发送异步请求,发送请求后,不会阻塞当前线程,而是将请求放入队列中,由线程池中的线程执行请求。

Call call = client.newCall(request);
call.enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        // 请求失败
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        // 请求成功
    }
});

OkHttpClient Builder的构造函数

OkHttpClient Builder的构造函数,主要是对一些参数赋值默认值,对一些对象进行初始化。

public OkHttpClient.Builder() {
    connectTimeout(10, TimeUnit.SECONDS);
    readTimeout(10, TimeUnit.SECONDS);
    writeTimeout(10, TimeUnit.SECONDS);

    // 设置默认的连接池
    connectionPool(new ConnectionPool(5, 5, 5, TimeUnit.MINUTES));

    // 设置默认的Dispatcher
    dispatcher(new Dispatcher());

    // 设置默认的ProxySelector
    proxySelector(ProxySelector.getDefault());

    // 设置默认的CookieJar
    cookieJar(CookieJar.NO_COOKIES);
}

Dispatcher的任务调度

Dispatcher是OkHttpClient中http请求的分发器,由它来决定如何调度请求。

Dispatcher内部维护了一个请求队列和一个线程池,当有新的请求到来时,Dispatcher会将请求放入队列中,然后由线程池中的线程执行请求。

Dispatcher提供了以下几个方法来控制任务调度:

  • setMaxRequests():设置最大请求数
  • setMaxRequestsPerHost():设置每个主机的最大请求数
  • setCorePoolSize():设置线程池的核心线程数
  • setMaximumPoolSize():设置线程池的最大线程数
  • setKeepAliveTime():设置线程池的空闲线程存活时间
public class Dispatcher {

    private int maxRequests = 64;
    private int maxRequestsPerHost = 5;
    private int corePoolSize = 0;
    private int maximumPoolSize = Integer.MAX_VALUE;
    private long keepAliveTime = 5;

    // 请求队列
    private final BlockingQueue<RealCall.AsyncCall> readyAsyncCalls = new LinkedBlockingQueue<>();

    // 线程池
    private final ExecutorService executorService;

    public Dispatcher() {
        this(Platform.get().defaultExecutorService());
    }

    public Dispatcher(ExecutorService executorService) {
        this.executorService = executorService;
    }

    // 省略其他方法

    public void enqueue(RealCall.AsyncCall call) {
        // 将请求放入队列中
        readyAsyncCalls.offer(call);

        // 启动线程池中的线程执行请求
        executorService.execute(call);
    }
}