线程池是什么、有什么用?
线程池是一种线程使用形式。
-
-
提高相应速度:可以使用线程池中闲置的线程,而不必等待线程的创建
-
有利于管理
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: