OkHttp3源码解析(二)OkHttp基本流程

本文详细解析了OkHttp的异步请求处理流程,从初始化OkHttpClient开始,到Request构造,再到RealCall的同步与异步执行机制,直至Dispatcher的调度策略。深入探讨了线程池管理、请求队列处理及AsyncCall执行过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先使用Okhttp发起一个异步请求,以此先简单分析OkHttp的大致流程。

okHttp使用:

OkHttpClient client=new OkHttpClient();
        Request request=new Request.Builder()
        .url("http://www.baidu.com")
        .build();
        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 {
            }
        });

Okhttp流程主要类 功能

OkHttpClient

使用建造者模式初始化连接池,Dispatcher等,为了节约资源推荐使用单列模式创建OkhttpClient对象,维护线程池比较耗资源。

Request

Http请求所需的URL,请求方法等,HTTP请求格式见上一章OkHttp3源码解析(一)Scoket实现HTTP请求

RealCall

实现Call接口。

1. 同步

直接调用RealCallexecute()方法。通过拦截器链对Request进行封装,发起请求,对得到的Response进行封装,最后返回。拦截器链下章讲。

2. 异步

调用enqueue(),最后会用调用Dispatcher的enqueue()。传入的是一个Runable的子类AsyncCall(RealCall内部类)

  @Override public void enqueue(Callback responseCallback) {
   synchronized (this) {
   //一个Call只能执行一次请求,不管是同步还是异步的。
     if (executed) throw new IllegalStateException("Already Executed");
     executed = true;
   }
   transmitter.callStart();
   //调用Dispatcher的enqueue方法
   client.dispatcher().enqueue(new AsyncCall(responseCallback));
 }

Dispatcher

包含线程池

  public synchronized ExecutorService executorService() {
    if (executorService == null) {
      executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
          new SynchronousQueue<>(), Util.threadFactory("OkHttp Dispatcher", false));
    }
    return executorService;
  }

经过RealCallenqueue(),来到了最后的Dispatcher的enqueue()

  void enqueue(AsyncCall call) {
    synchronized (this) {
    //直接添加到准备队列,不同于以往的判断添加,
      readyAsyncCalls.add(call);
      if (!call.get().forWebSocket) {
        AsyncCall existingCall = findExistingCallWithHost(call.host());
        if (existingCall != null) call.reuseCallsPerHostFrom(existingCall);
      }
    }
    promoteAndExecute();
  }

后面执行promoteAndExecute();
遍历等待请求序列。
判断正在执行的请求数是否,小于64,并且同时请求的主机数小于5,不满足条件,直接Break停止当前遍历。
符合判断,则将当前等待执行请求加入临时可以执行序列executableCalls,并且将当前请求添加到正在请求序列。继续遍历,知道遍历完所有等待请求序列或者是正在执行序列,主机数超过上限。
遍历可以执行序列,放入线程池执行请求。

 private boolean promoteAndExecute() {
    assert (!Thread.holdsLock(this));

    List<AsyncCall> executableCalls = new ArrayList<>();
    boolean isRunning;
    synchronized (this) {
      for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
        AsyncCall asyncCall = i.next();
        //判断正在执行请求数是否大于64,连接主机数大于5.不符合条件直接Break;
        if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
        if (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // Host max capacity.
        i.remove();
        asyncCall.callsPerHost().incrementAndGet();
        //符合要求,添加到可以执行List中
        executableCalls.add(asyncCall);
       //添加到正在执行List
        runningAsyncCalls.add(asyncCall);
      }
      isRunning = runningCallsCount() > 0;
    }
//可以执行List中有任务,放入线程池执行。
    for (int i = 0, size = executableCalls.size(); i < size; i++) {
      AsyncCall asyncCall = executableCalls.get(i);
      asyncCall.executeOn(executorService());
    }
    return isRunning;
  }

NamedRunnable

NamedRunnable实现Runable接口,并包含抽象方法execute。并在run方法中执行execute()

NamedRunnable主要代码。

  @Override
  public void run() {
      exexute();
  }
  abstract void exexute();

AsyncCall

RealCall内部类,继承抽象类NamedRunnable,实现抽象方法execute(),当DIspatcher调用线程池执行请求,最终会到AsyncCall的execute()。通过拦截器链处理得到Response,下章讲。

  @Override protected void execute() {
   try {
   //拦截器链处理
     Response response = getResponseWithInterceptorChain();
     //成功,回调CallBack
        responseCallback.onResponse(RealCall.this, response);
   } catch (IOException e) {
//失败,回调CallBack
       responseCallback.onFailure(RealCall.this, e);
   } finally {
   //请求结束,一些列处理,包括从正在执行系列中移除等操作。
     client.dispatcher().finished(this);
   }
 }

流程图(待补)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值