源码阅读--OkHttp3

来源:互联网 发布:java zxing 二维码 编辑:程序博客网 时间:2024/05/17 00:17

用法在这里
http://blog.csdn.net/itachi85/article/details/51190687

大致流程如下:
1.准备OkHttpClient
2.准备requestBuilder
3.mOkHttpClient.newCall(request).enqueue

enqueue的调用流程如下:

  @Override public void enqueue(Callback responseCallback) {    synchronized (this) {      if (executed) throw new IllegalStateException("Already Executed");      executed = true;    }    captureCallStackTrace();    client.dispatcher().enqueue(new AsyncCall(responseCallback));//--------------------  }

dispatcher的enqueue实现如下:

  synchronized void enqueue(AsyncCall call) {    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {      runningAsyncCalls.add(call);      executorService().execute(call);//------------------执行网络操作    } else {      readyAsyncCalls.add(call);    }  }

流程没什么难度。接下来看一下OkHttpClient的实现

ConnectionPool

OkHttpClient是通过Builder来实现的,也就是建造者模式,里面有一个重要的数据结构ConnectionPool

public final class ConnectionPool {  //-------------------------ThreadPoolExecutor,我以前的blog有讲过  private static final Executor executor = new ThreadPoolExecutor(0 /* corePoolSize */,      Integer.MAX_VALUE /* maximumPoolSize */, 60L /* keepAliveTime */, TimeUnit.SECONDS,      new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp ConnectionPool", true));  //-----------------------------------最大空闲连接  private final int maxIdleConnections;  private final long keepAliveDurationNs;  private final Runnable cleanupRunnable = new Runnable() {    @Override public void run() {      while (true) {        long waitNanos = cleanup(System.nanoTime());//----------------------//如果空闲连接keepAlive时间超过5分钟,或者空闲连接数超过5个,则从Deque中移除此连接        if (waitNanos == -1) return;        if (waitNanos > 0) {          long waitMillis = waitNanos / 1000000L;          waitNanos -= (waitMillis * 1000000L);          synchronized (ConnectionPool.this) {            try {                //------------------------------wait在waitMillis毫秒后还有等待os调用分配资源,所以停止运行时间是不确定的,但至少是waitMillis毫秒。               ConnectionPool.this.wait(waitMillis, (int) waitNanos);            } catch (InterruptedException ignored) {            }          }        }      }    }  };  private final Deque<RealConnection> connections = new ArrayDeque<>();//---------------------------------下面有解释(核心)  final RouteDatabase routeDatabase = new RouteDatabase();//------------------------------------------LinkedHashSet,HashSet的子类,说白了就是LinkedHashMap  boolean cleanupRunning;  //----------------------------默认构造函数,其实构造函数里面就对部分参数赋值  public ConnectionPool() {    this(5, 5, TimeUnit.MINUTES);  }  public ConnectionPool(int maxIdleConnections, long keepAliveDuration, TimeUnit timeUnit) {    this.maxIdleConnections = maxIdleConnections;    this.keepAliveDurationNs = timeUnit.toNanos(keepAliveDuration);    // Put a floor on the keep alive duration, otherwise cleanup will spin loop.    if (keepAliveDuration <= 0) {      throw new IllegalArgumentException("keepAliveDuration <= 0: " + keepAliveDuration);    }  }  //------------------------遍历connections缓存列表,当某个连接计数的次数小于限制的大小并且request的地址和缓存列表中此连接的地址完全匹配,则直接复用缓存列表中的connection  RealConnection get(Address address, StreamAllocation streamAllocation, Route route) {    assert (Thread.holdsLock(this));    for (RealConnection connection : connections) {      if (connection.isEligible(address, route)) {        streamAllocation.acquire(connection);        return connection;      }    }    return null;  }  void put(RealConnection connection) {    assert (Thread.holdsLock(this));    if (!cleanupRunning) {      cleanupRunning = true;      executor.execute(cleanupRunnable);//-----------------------清理线程    }    connections.add(connection);  }  //--------------------------------------------//如果空闲连接keepAlive时间超过5分钟,或者空闲连接数超过5个,则从Deque中移除此连接  long cleanup(long now) {    int inUseConnectionCount = 0;    int idleConnectionCount = 0;    RealConnection longestIdleConnection = null;    long longestIdleDurationNs = Long.MIN_VALUE;    synchronized (this) {      for (Iterator<RealConnection> i = connections.iterator(); i.hasNext(); ) {        RealConnection connection = i.next();        // If the connection is in use, keep searching.        if (pruneAndGetAllocationCount(connection, now) > 0) {//----------里面有Reference,用来计数的          inUseConnectionCount++;          continue;        }        idleConnectionCount++;        // If the connection is ready to be evicted, we're done.        long idleDurationNs = now - connection.idleAtNanos;        if (idleDurationNs > longestIdleDurationNs) {          longestIdleDurationNs = idleDurationNs;          longestIdleConnection = connection;        }      }      if (longestIdleDurationNs >= this.keepAliveDurationNs          || idleConnectionCount > this.maxIdleConnections) {        // We've found a connection to evict. Remove it from the list, then close it below (outside        // of the synchronized block).        connections.remove(longestIdleConnection);//----------------------//如果空闲连接keepAlive时间超过5分钟,或者空闲连接数超过5个,则从Deque中移除此连接      } else if (idleConnectionCount > 0) {        return keepAliveDurationNs - longestIdleDurationNs;      } else if (inUseConnectionCount > 0) {        return keepAliveDurationNs;      } else {        cleanupRunning = false;        return -1;      }    }    closeQuietly(longestIdleConnection.socket());    // Cleanup again immediately.    return 0;  }}

ArrayDeque的解释:
有三个重要的数据结构

    private transient E[] elements;    private transient int head;    private transient int tail;

很明显,类似于链表。其中的数组元素在add等方法执行时不移动,发生变化的只是head和tail指针。
头指针head从0开始,尾指针tail从n开始,在头部插入数据时,head减一,在尾部插入数据时,tail加一。(取余,所以是循环)
当head==tail时说明数组的容量满足不了当前的情况,此时需要扩大容量为原来的二倍。

0 0
原创粉丝点击