快手内推

概述

了解线程池的基础概念有利于阅读其源码,以及解决或者优化线程池导致的各种问题。

线程池作用

  1. 节省资源。
    使用线程池可以避免每次异步操作都去创建一个线程。
  2. 提高响应速度。
    由于线程池本身会创建一些线程,能够节省创建线程池的时间。
  3. 更好的管理线程。
    线程池可以控制其线程的创建停止,存活个数等等。不仅能够保证系统的稳定运行,同时也可以更加方便的性能调优。

核心参数

  • corePoolSize
    核心线程数。有新任务要执行时,如果当前工作线程没有到达corePoolSize,每次都会新建线程。线程数到达corePoolSize之后才会放到工作队列。
  • maximumPoolSize
    线程池中线程的最大个数。当线程数到达corePoolSize,并且工作队列已满的时候,会新建线程并且执行任务,但是线程总数不能大于maximumPoolSize。
  • keepAliveTime
    线程维持时间。corePoolSize<当前线程个数
  • unit
    单位。keepAliveTime的单位
  • workQueue
    工作队列。用来存储还没执行的任务,在任务被执行之前,会一直存储在这个队列中。(这块内容在后面有详述)
  • threadFactory
    线程工厂。用于创建线程,用来满足开发者对线程的自定义需求。
  • handler
    task被拒绝之后执行的逻辑。
    有两种情况会执行到:
  1. 当线程数到达maximumPoolSize,并且workQueue到达上限后会触发
  2. 当线程池不是running状态的时候,即已经被shutdown或者stop了。

目前有这几种饱和策略:

  1. AbortPolicy
    当任务被拒绝的时候,报异常 RejectedExecutionException。
  2. CallerRunsPolicy
    当任务被拒绝的时候,,会直接运行在调用execute的那个线程。如果在这个过程中任务被丢弃了,那么会停止。
  3. DiscardOldestPolicy
    当任务被拒绝的时候,会丢弃在队列中等待最久的请求,然后再次尝试此执行此任务。如果在这个过程中任务被丢弃了,那么会停止。
  4. DiscardPolicy
    当任务被拒绝的时候,直接就丢弃这个任务。

任务队列

任务队列是线程池的核心参数之一,由于其比较重要,因此单独开了一个标题。

笔者针对ArrayBlockingQueue的源码有过具体分析,有兴趣的读者可以看下:ReentrantLock和AQS 源码解析

常用的任务队列有以下几种:

  1. ArrayBlockingQueue
    数组队列。先进先出原则。
  2. DelayQueue
    使用优先级队列,以delay的时间为作为优先级的标准。队列头部将是超过delay时间最久的任务,如果队列中没有任务到期,头部将为空。(优先级队列是数组为基础的堆结构)
  3. LinkedBlockingQueue
    链表队列。先进先出原则。
  4. LinkedBlockingDeque
    链表双向队列。默认是先进先出原则。与LinkedBlockingQueue的差异就是双向队列,与LinkedBlockingQueue相比支持”头部插入“、”支持先进后出“等操作,但是由于有更多的引用,因此更加消耗资源。
  5. PriorityBlockingQueue
    存储在数组为基础的堆结构中。开发者可以自己设置自己的优先级标准,堆中的对象会根据优先级排序。

线程池内部状态

  • RUNNING
    会接受新的任务,也会执行队列中的任务。
  • SHUTDOWN
    不会接受新的任务,但是会执行队列中的任务。
  • STOP
    不会接受新的任务,也不会执行队列中的任务。
  • TIDYING
    所有的任务已经终止,并且没有正在工作的线程。此时线程池会进入到TIDYING状态,并且马上会执行terminated()方法来终止线程。
  • TERMINATED
    执行terminated()方法结束之后就会进入TERMINATED状态。

各状态变化的时机

  • RUNNING -> SHUTDOWN
    调用shutdown()方法,或者也有可能触发了finalize()方法。
    finalize()方法会在线程池不再被引用且没有线程存活的时候触发。
  • (RUNNING or SHUTDOWN) -> STOP
    shutdownNow()方法
  • SHUTDOWN -> TIDYING
    所有的任务已经终止,并且没有正在工作的线程
  • STOP -> TIDYING
    没有正在工作的线程
  • TIDYING -> TERMINATED
    触发了terminated(),并且执行结束。

你可能感兴趣的:(【Android】,【Java】)