简介

其实也不用简介了吧,线程池这个太熟悉了,无非就是七个参数和运行过程,这个都说烂了,就略过吧。

四种线程池

  • newFixedThreadPool(int nThreads)
    固定线程池,线程数量是固定的,队列使用的是链表阻塞队列(LinkedBlockingQueue),队列是无限长的。
  • newCachedThreadPool()
    缓存线程池,核心线程数为0,最大线程数为Integer.MAX_VALUE,也就是说可以不断的新建线程,任务执行完成之后,线程都会被回收。
  • newSingleThreadPool()
    单个线程池,核心线程数和最大线程数都是1,但是队列是链表阻塞队列,无限长。
  • newScheduledThreadPool(int corePoolSize)
    周期性线程池,也就是说可以周期地执行任务,最大线程数是Integer.MAX_VALUE,可以无限创建线程,队列是DelayedWorkQueue()。
  • 这四种线程池本质上都是调用的ThreadPoolExecutor构造方法

阻塞队列

  • 含义:阻塞队列和一般的队列的区别就在于:一般队列在获取值时,如果队列为空,会直接返回一个空值;而阻塞队列不一样,会阻塞获取元素的线程,直到队列中有值,会唤醒获取元素的线程,获取元素返回。
  • ArrayBlockingQueue(数组阻塞队列)
    因为是基于数组的阻塞队列,所以在初始化的时候就会指定其大小,队列长度是固定的。
  • LinkedBlockingQueue(链表阻塞队列)
    链表是没有长度限制的,它的最大长度是Integer.MAX_VALUE,当然也可以指定其长度大小,newFixedThreadPool和newSingleThreadPool中都是用的这种阻塞队列,虽然大小没限制,但它依旧是一个有界的阻塞队列。
  • DelayQueue(延迟阻塞队列)
    只有当指定的延迟时间到了,才能获取到队列中的元素,它是一个无界的队列,所以它不会阻塞生产者,生产者可以随意往里面写入元素,但是在元素的延迟时间到之前,消费者都会阻塞住,等待延迟时间,newScheduledThreadPool就是用的这种阻塞队列。
  • PriorityBlockingQueue(优先级队列)
    带有优先级的阻塞队列,不再遵循队列的FIFO元素,会让优先级高的元素先出队,也是一个无界队列。
  • SynchronousQueue(同步队列)
    这个一个特殊的阻塞队列,它本身是不存放任何元素,也就是长度始终为0,当生产者往里面写入元素的时候,就会被阻塞住,直到有消费者取出元素才会再唤醒生产者,newCachedThreadPool用的就是这个阻塞队列。

拒绝策略

当没有空闲线程,且队列也满了的时候,线程池就会执行拒绝策略了。

  • AbortPolicy
    这个策略会丢弃任务,并抛出异常,这是线程池默认的拒绝策略,需要处理好抛出的异常,否则会影响后续的任务执行。
  • DiscardPolicy
    直接丢弃多出来的任务,不会抛出异常
  • DiscardOldestPolicy
    丢弃阻塞队列中最老的任务,且将新任务添加进去
  • CallerRunsPolicy
    使用调用者自己来执行任务,由于是调用者自己一个人执行任务,如果任务提交速度过快,可能会造成程序阻塞,导致性能下降。
  • 自定义拒绝策略
    实现RejectedExecutionHandle接口就可以了。