OkHttp的分发器线程池

本文分析了OkHttp分发器中线程池的配置和工作原理,包括核心线程数、最大线程数、缓存时间和等待队列等参数。详细解释了在不同情况下线程池如何处理任务,如使用无界队列可能导致最大线程数参数无效,以及SynchronousQueue如何实现最大并发量。同时提到了内存限制对线程数量的影响。
public synchronized ExecutorService executorService() {
    if (executorService == null) {
      executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
          new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
    }
    return executorService;
  }

OkHttp 的分发器中的线程池定义如上,其实就和 Executors.newCachedThreadPool() 创建的线程一样,分析一下参数:

  • 第一个参数:核心线程数(一直存在的线程数),为零表示线程池不会一直缓存线程;
  • 第二个参数:最大线程数(多出的线程会被缓存);
  • 第三个参数:最大缓存时间(线程池中的所有线程都是在60s内没有工作就会被回收);
  • 第四个参数:缓存时间单位;
  • 第五个参数:阻塞等待队列;
  • 第六个参数:线程工厂(用于生产线程)。

当需要线程池执行任务时,有如下几种情况:

a. 当前线程数量小于核心线程数,将新建(核心)线程来处理被添加的任务;

b. 当前线程数量大于等于核心线程数,存在空闲线程,将使用空闲线程来执行新任务;

c. 当前线程数量大于等于核心线程数,不存在空闲线程,新任务将被添加到等待队列,

​ 添加成功则等待空闲线程;

​ 添加失败: (1) 线程数小于 maximumPoolSize,新建线程执行任务;

​ (2) 线程数大于等于 maximunPoolSize,拒绝此任务。

可以指定不同的等待队列,这样会有不同的线程池排队机制。一般来说,等待队列 BlockingQueue 有:ArrayBlockingQueueLinkedBlockingQueueSynchronousQueue

  1. ArrayBlockingQueue: 基于数组的阻塞队列,初始化需要指定固定大小。

当使用此队列时,向线程池提交任务,会首先加入到等待队列中,当等待队列满了之后,再次提交任务,尝试加入队列就会失败,这时就会检查如果当前线程池中的线程数未达到最大线程,则会新建线程执行新提交的任务。所以最终可能出现后提交的任务先执行,而先提交的任务一直在等待。

  1. LinkedBlockingQueue:基于链表实现的阻塞队列,初始化可以指定大小,也可以不指定。

当指定大小后,行为就与 ArrayBlockingQueue 一致。而如果未指定大小,则会使用默认的Integer.MAX_VALUE 作为队列的大小。这时候就会出现线程池的最大线程数参数无用,因为无论如何,向线程池提交任务加入等待队列都会成功。最终意味着所有任务都是在核心线程执行。如果核心线程一直被占用,那就一直等待。

  1. SynchronousQueue:无容量的队列。

    使用此队列意味着希望获得最大并发量。因为无论如何,向线程池提交任务,往队列提交任务都会失败。而失败后如果没有空闲的非核心线程,就会检查如果当前的线程池中的线程数未达到最大线程,则会新建线程执行新提交的任务。完全没有任何等待,唯一制约它的就是最大的线程数量。因此一般配合Integer.MAX_VALUE实现真正的无等待。

但需要注意的是进程的内存是存在限制的,而每一个线程都需要分配一定的内存。所以线程并不是无限个数。那么当设置最大线程数为Integer.MAX_VALUE时,OkHttp同时还有最大请求任务个数(默认64)和每个域名最大请求数(默认5)的限制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值