你还不了解线程池原理?赶忙来补一下

1、为何要用线程池

  1. 下降资源消耗。经过重复利用已建立的线程下降线程建立、销毁线程形成的消耗。程序员

  2. 提升响应速度。当任务到达时,任务能够不须要等到线程建立就能当即执行。数组

  3. 提升线程的可管理性。线程是稀缺资源,若是无限制的建立,不只会消耗系统资源,还会下降系统的稳定性,使用线程池能够进行统一的分配、调优和监控缓存

2、ThreadPoolExecutor线程池类参数详解

参数 说明
corePoolSize 核心线程数量,线程池维护线程的最少数量
maximumPoolSize 线程池维护线程的最大数量
keepAliveTime 线程池除核心线程外的其余线程的最长空闲时间,超过该时间的空闲线程会被销毁
unit keepAliveTime的单位,TimeUnit中的几个静态属性:NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS
workQueue 线程池所使用的任务缓冲队列
threadFactory 线程工厂,用于建立线程,通常用默认的便可
handler 线程池对拒绝任务的处理策略

当线程池任务处理不过来的时候(何时认为处理不过来后面描述),能够经过handler指定的策略进行处理,ThreadPoolExecutor提供了四种策略:并发

  1. ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常;也是默认的处理方式。
  2. ThreadPoolExecutor.DiscardPolicy:丢弃任务,可是不抛出异常。
  3. ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,而后从新尝试执行任务(重复此过程)
  4. ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

能够经过实现RejectedExecutionHandler接口自定义处理方式。函数

3、线程池任务执行

1. 添加执行任务

  • submit() 该方法返回一个Future对象,可执行带返回值的线程;或者执行想随时能够取消的线程。Future对象的get()方法获取返回值。Future对象的cancel(true/false)取消任务,未开始或已完成返回false,参数表示是否中断执行中的线程
  • execute() 没有返回值。

2. 线程池任务提交过程

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处理被拒绝的任务。

注意:

  1. 当workQueue使用的是无界限队列时,maximumPoolSize参数就变的无心义了,好比new LinkedBlockingQueue(),或者new ArrayBlockingQueue(Integer.MAX_VALUE);
  2. 使用SynchronousQueue队列时因为该队列没有容量的特性,因此不会对任务进行排队,若是线程池中没有空闲线程,会当即建立一个新线程来接收这个任务。maximumPoolSize要设置大一点。
  3. 核心线程和最大线程数量相等时keepAliveTime无做用.

3. 线程池关闭

3.1. shutdown() 不接收新任务,会处理已添加任务 3.2. shutdownNow() 不接受新任务,不处理已添加任务,中断正在处理的任务

4. 经常使用队列介绍

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

5. Executors线程工厂类

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开发手册中对线程池的使用规范

  1. 【强制】建立线程或线程池时请指定有意义的线程名称,方便出错时回溯。 正例:
public class TimerTaskThread extends Thread {
    public TimerTaskThread(){
        super.setName("TimerTaskThread"); 
        ...
    }
}
  1. 【强制】线程资源必须经过线程池提供,不容许在应用中自行显式建立线程。 说明: 使用线程池的好处是减小在建立和销毁线程上所花的时间以及系统资源的开销,解决资 源不足的问题。若是不使用线程池,有可能形成系统建立大量同类线程而致使消耗完内存或者 “过分切换”的问题。

  2. 【强制】线程池不容许使用 Executors 去建立,而是经过 ThreadPoolExecutor 的方式,这样 的处理方式让写的同窗更加明确线程池的运行规则,规避资源耗尽的风险。

说明: Executors 返回的线程池对象的弊端以下: 1) FixedThreadPool 和 SingleThreadPool: 容许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而致使 OOM。 2) CachedThreadPool 和 ScheduledThreadPool: 容许的建立线程数量为 Integer.MAX_VALUE, 可能会建立大量的线程,从而致使 OOM。

6. 总结

ThreadPoolExecutor经过几个核心参数来定义不一样类型的线程池,适用于不一样的使用场景;其中在任务提交时,会依次判断corePoolSize, workQueque, 及maximumPoolSize,不一样的状态不一样的处理。技术领域水太深,若是不是平常使用,基本一段时间后某些知识点就忘的差很少了,所以阶段性地回顾与总结,对夯实本身的技术基础颇有必要。

点关注,不迷路,这是一个程序员都想要关注的公众号

相关文章
相关标签/搜索