OKHttp3源码分析-ConnectionInterceptor

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jPesRXcb-1615889568086)(https://github.com/wfeii/wfeii.github.io_raw_important/blob/master/OkHttpClient3.4/ConnectionInterceptor%E7%9A%84%E7%9B%B8%E5%85%B3%E7%B1%BB%E5%9B%BE.png?raw=true)]

主要的类包含ConnectInterceptorStreamAllocationRealConnectionConnectionPool

我们先分析ConnectionPool,然后分析ConnectionInterceptor

连接池

ConnectionPool作用主要是复用Http连接,避免网络连接的时延,以及避免TCP调谐带来的带宽过小的问题。ConnectionPool主要有两个方法

  • get方法用于获取连接。
  • put方法用于添加连接。

get方法

public final class ConnectionPool {
   
    private final Deque<RealConnection> connections = new ArrayDeque<>();
	@Nullable RealConnection get(Address address, StreamAllocation streamAllocation, Route route) {
   
    	assert (Thread.holdsLock(this));
    	for (RealConnection connection : connections) {
   
      		if (connection.isEligible(address, route)) {
   
        		streamAllocation.acquire(connection, true);
        		return connection;
      		}
    	}
  		return null;
  }	    
}

遍历连接池的连接,addressroute作为参数调用RealConnection对象的方法isEligible来判断连接是否合适。

如果合适,就调用StreamAllocationacquire方法,然后返回RealConnection对象。当所有的连接都不合适的时候返回null

我们来看一下StreamAllocationacquire方法。

public final class StreamAllocation {
   
    public void acquire(RealConnection connection, boolean reportedAcquired) {
   
        assert (Thread.holdsLock(connectionPool));
        if (this.connection != null) throw new IllegalStateException();
        this.connection = connection;
        this.reportedAcquired = reportedAcquired;
        connection.allocations.add(new StreamAllocationReference(this, callStackTrace));
 	}
}

先判断StreamAllocation的变量connection是否为null。不为null,说明已经包含一个连接了,直接抛出状态异常。

最重要的创建一个StreamAllocationReference对象,StreamAllocationReferenceStreamAllocation的弱引用。然后添加到RealConnection对象connectionallocations变量中。这样就可以遍历RealConnectionallocations变量来查看是否被StreamAllocation使用中。

put方法

public final class ConnectionPool {
   
    private final Deque<RealConnection> connections = new ArrayDeque<>();
	void put(RealConnection connection) {
   
        assert (Thread.holdsLock(this));
        if (!cleanupRunning) {
   
          cleanupRunning = true;
          executor.execute(cleanupRunnable);
        }
        connections.add(connection);
  	}
}

put方法比较简单,先是判断cleanupRunningcleanupRunning表示清理连接的工作正在执行。如果没有执行就调用线程池来执行cleanupRunnable。然后是把RealConnection对象connection添加到变量connections中。

连接清理

public final class ConnectionPool {
   
    private final Runnable cleanupRunnable = new Runnable() {
   
    @Override public void run() {
   
      while (true) {
   
        //通过调用cleanup方法来获取等待时间。
        long waitNanos = cleanup(System.nanoTime());
        //等待时间是-1直接返回
        if (waitNanos == -1) return;
        if (waitNanos > 0) {
   
          long waitMillis = waitNanos / 1000000L;
          waitNanos -= (waitMillis * 1000000L);
          synchronized (ConnectionPool.this) {
   
            try {
   
              //设置等待时间。
              ConnectionPool.this.wait(waitMillis, (int) waitNanos);
            } catch (InterruptedException ignored
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值