美文网首页
OkHttp的分发器线程池

OkHttp的分发器线程池

作者: Mr_Hongdou | 来源:发表于2020-04-06 17:20 被阅读0次
    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)的限制。

    相关文章

      网友评论

          本文标题:OkHttp的分发器线程池

          本文链接:https://www.haomeiwen.com/subject/pwbbphtx.html