下降资源消耗。经过重复利用已建立的线程下降线程建立、销毁线程形成的消耗。程序员
提升响应速度。当任务到达时,任务能够不须要等到线程建立就能当即执行。数组
提升线程的可管理性。线程是稀缺资源,若是无限制的建立,不只会消耗系统资源,还会下降系统的稳定性,使用线程池能够进行统一的分配、调优和监控缓存
参数 | 说明 |
---|---|
corePoolSize | 核心线程数量,线程池维护线程的最少数量 |
maximumPoolSize | 线程池维护线程的最大数量 |
keepAliveTime | 线程池除核心线程外的其余线程的最长空闲时间,超过该时间的空闲线程会被销毁 |
unit | keepAliveTime的单位,TimeUnit中的几个静态属性:NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS |
workQueue | 线程池所使用的任务缓冲队列 |
threadFactory | 线程工厂,用于建立线程,通常用默认的便可 |
handler | 线程池对拒绝任务的处理策略 |
当线程池任务处理不过来的时候(何时认为处理不过来后面描述),能够经过handler指定的策略进行处理,ThreadPoolExecutor提供了四种策略:并发
能够经过实现RejectedExecutionHandler接口自定义处理方式。函数
2.1. 若是此时线程池中的数量小于corePoolSize,即便线程池中的线程都处于空闲状态,也要建立新的线程来处理被添加的任务。线程
2.2. 若是此时线程池中的数量等于corePoolSize,可是缓冲队列workQueue未满,那么任务被放入缓冲队列。code
2.3. 若是此时线程池中的数量大于等于corePoolSize,缓冲队列workQueue满,而且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务。对象
2.4. 若是此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,而且线程池中的数量等于maximumPoolSize,那么经过 handler所指定的策略来处理此任务。接口
2.5. 当线程池中的线程数量大于 corePoolSize时,若是某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池能够动态的调整池中的线程数。队列
总结即:处理任务判断的优先级为 核心线程corePoolSize、任务队列workQueue、最大线程maximumPoolSize,若是三者都满了,使用handler处理被拒绝的任务。
注意:
3.1. shutdown() 不接收新任务,会处理已添加任务 3.2. shutdownNow() 不接受新任务,不处理已添加任务,中断正在处理的任务
4.1. ArrayBlockingQueue: 这是一个由数组实现的容量固定的有界阻塞队列.
4.2. SynchronousQueue: 没有容量,不能缓存数据;每一个put必须等待一个take; offer()的时候若是没有另外一个线程在poll()或者take()的话返回false。
4.3. LinkedBlockingQueue: 这是一个由单链表实现的默认无界的阻塞队列。LinkedBlockingQueue提供了一个可选有界的构造函数,而在未指明容量时,容量默认为Integer.MAX_VALUE。
队列操做:
方法 | 说明 |
---|---|
add | 增长一个元索; 若是队列已满,则抛出一个异常 |
remove | 移除并返回队列头部的元素; 若是队列为空,则抛出一个异常 |
offer | 添加一个元素并返回true; 若是队列已满,则返回false |
poll | 移除并返回队列头部的元素; 若是队列为空,则返回null |
put | 添加一个元素; 若是队列满,则阻塞 |
take | 移除并返回队列头部的元素; 若是队列为空,则阻塞 |
element | 返回队列头部的元素; 若是队列为空,则抛出一个异常 |
peek | 返回队列头部的元素; 若是队列为空,则返回null |
1. Executors.newCachedThreadPool(); 说明: 建立一个可缓存线程池,若是线程池长度超过处理须要,可灵活回收空闲线程,若无可回收,则新建线程. 内部实现:new ThreadPoolExecutor(0,Integer.MAX_VALUE,60L,TimeUnit.SECONDS,new SynchronousQueue<runnable>());</runnable>
2. Executors.newFixedThreadPool(int); 说明: 建立一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。 内部实现:new ThreadPoolExecutor(nThreads, nThreads,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<runnable>());</runnable>
3. Executors.newSingleThreadExecutor(); 说明:建立一个单线程化的线程池,它只会用惟一的工做线程来执行任务,保证全部任务按照顺序执行。 内部实现:new ThreadPoolExecutor(1,1,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<runnable>())</runnable>
4. Executors.newScheduledThreadPool(int); 说明:建立一个定长线程池,支持定时及周期性任务执行。 内部实现:new ScheduledThreadPoolExecutor(corePoolSize)
【附】阿里巴巴Java开发手册中对线程池的使用规范
public class TimerTaskThread extends Thread { public TimerTaskThread(){ super.setName("TimerTaskThread"); ... } }
【强制】线程资源必须经过线程池提供,不容许在应用中自行显式建立线程。 说明: 使用线程池的好处是减小在建立和销毁线程上所花的时间以及系统资源的开销,解决资 源不足的问题。若是不使用线程池,有可能形成系统建立大量同类线程而致使消耗完内存或者 “过分切换”的问题。
【强制】线程池不容许使用 Executors 去建立,而是经过 ThreadPoolExecutor 的方式,这样 的处理方式让写的同窗更加明确线程池的运行规则,规避资源耗尽的风险。
说明: Executors 返回的线程池对象的弊端以下: 1) FixedThreadPool 和 SingleThreadPool: 容许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而致使 OOM。 2) CachedThreadPool 和 ScheduledThreadPool: 容许的建立线程数量为 Integer.MAX_VALUE, 可能会建立大量的线程,从而致使 OOM。
ThreadPoolExecutor经过几个核心参数来定义不一样类型的线程池,适用于不一样的使用场景;其中在任务提交时,会依次判断corePoolSize, workQueque, 及maximumPoolSize,不一样的状态不一样的处理。技术领域水太深,若是不是平常使用,基本一段时间后某些知识点就忘的差很少了,所以阶段性地回顾与总结,对夯实本身的技术基础颇有必要。