线程池基础知识 线程池基础

线程池是什么、有什么用?

线程池是一种线程使用形式。

  • 减少资源损耗:创建/销毁线程需要消耗系统资源,线程池可以复用已创建的线程,同时可以控制线程数量

  • 提高相应速度:可以使用线程池中闲置的线程,而不必等待线程的创建

  • 有利于管理

7大参数

参数类型 参数名 含义
int corePoolSize 核心线程数最大值
int maximumPoolSize 线程总数最大值
long keepAliveTime 非核心线程线程最大闲置时间
TimeUnit unit keepAliveTime属性的单位
BlockingQueue<Runnable> workQueue 等待队列
ThreadFactory threadFactory 线程工厂
RejectedExecutionHandler handler 拒绝策略者

下面我们简单介绍一下这些参数的含义

  • corePoolSize:核心线程数最大值

    线程池中有两种线程,一个是核心线程另一个是非核心线程。核心线程在默认情况下会一直存在于线程池之中,不因为闲置时间过长而被销毁。(当然,也可以通过设置allowCoreThreadTimeOut的值为true,使得核心线程也会被销毁,默认值为false)。

    关于这个核心线程数最大值有这样一个默认规则:

    CPU密集型任务,设置核心线程数为CPU核心数+1;IO密集型任务,设置核心线程数为CPU核心数*2

  • maximumPoolSize:线程总数最大值

    指定线程总数的上限。线程总数 = 核心线程数 + 非核心线程数

  • keepAliveTime:线程闲置时间

    默认情况下是为了去销毁非核心线程,当一个非核心线程空闲时间大于这个空闲等待时间时,这个非核心线程将会被销毁

  • unit:线程闲置时间的时间单位

    是一个枚举属性,包括以下属性:

    • NANOSECONDS:微毫秒/纳秒 10^(-9) 秒

    • MICROSECONDS:微妙 10^(-6)秒

    • MILLISECONDS:毫秒 10^(-3)秒

    • SECONDS:秒

    • MINUTES:分钟

    • HOURS:小时

    • DAYS:天

  • workQueue:阻塞队列

    当线程不够用时,将想要执行的任务放于阻塞队列之中,常用的4个阻塞队列有:

    • LinkedBlockingQueue

      链式阻塞队列,底层数据结构是链表,默认大小是Integer.MAX_VALUE

    • ArrayBlockingQueue:

      数组阻塞队列,底层数据结构是数组,需要指定队列大小

    • SynchronousQueue

      同步队列,内部容量为0,每个put操作必须等待一个take操作,反之亦然

    • DelayQueue

      延迟队列,该队列中的元素只有当其指定的延迟时间到了,才能从该队列中获取元素

以上5个是必须参数,接下来介绍两个非必须的参数

  • threadFactory:创建线程的工厂

    用于批量创建线程,统一在创建进程时设置一些参数,如是否为守护线程、线程的优先级等,若不进行指定,则创建一个默认的工厂

  • handler:拒绝处理策略

    当线程数量大于最大线程数时就会采用拒绝处理策略,常用的有以下四种:

    • ThreadPoolExecutor.AbortPolicy

      是默认的决绝策略,丢弃任务并抛出一个RejectedExecutionException异常

    • ThreadPoolExecutor.DiscardPolicy

      只丢弃任务,不抛出异常

    • ThreadPoolExecutor.DiscardOldestPolicy

      丢弃队列头部的任务,并继续尝试执行执行任务(一直重复该过程)

    • ThreadPoolExecutor.CallerRunPolicy

      由调用线程处理该任务

4种常见线程池

  • newCachedThreadPool:

    创建一个没有核心线程、最大线程数量为Integer.MAX_VALUE、默认等待时间为60s、阻塞队列为同步队列的线程池。好处在于每一个任务都会被马上执行,坏处是当任务数过大会创建大量线程导致系统崩溃

  • newFixedThreadPool:

    创建一个有且只有只有核心线程、线程数由用户指定的、阻塞队列为链式阻塞队列的线程池。好处是线程不会被回收,有较高的响应速度。坏处是阻塞队列没有上限,任务过多可能会崩溃

  • newSingleThreadExecutor:

    创建一个有且只有一个核心线程的、阻塞队列为链式阻塞队列的线程池。适用于对任务执行顺序有要求的场景

  • newSecheduledThreadPool:

    创建一个核心数由用户指定、最大线程数量为Integer.MAX_VALUE、默认等待时间为10ms、阻塞队列为延迟队列的线程池。支持定时及周期性任务执行。