线程池
Posted 小刘你最强
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程池相关的知识,希望对你有一定的参考价值。
线程池
线程池的优点/使用场景
- 降低资源消耗.通过重复利用自己创建的线程降低线程创建和销毁造成的消耗.
- 提高响应速度.当任务到达时,任务可以不需要等到线程的创建,就能立即执行.
- 提高线程的可管理性.线程是稀缺资源,如果无限的创阿金,不仅会消耗资源,还会较低系统的稳定性,使用线程池可以进行统一分配,调优和监控.
Java 中的线程池是通过 Executor 框架实现的,该框架中用到了 Executor、Executors、ExecutorService、ThreadPoolExecutor 这几个类。
创建方式
jdk提供的4种线程池
ExecutorService pool1 = Executors.newSingleThreadExecutor();//创建单线程池
ExecutorService pool2 = Executors.newCachedThreadPool();//缓存的线程池
ExecutorService pool3 = Executors.newFixedThreadPool(4);//固定大小的线程池
ScheduledExecutorService pool4 = Executors.newScheduledThreadPool(4);//计划任务线程池
CachedThreadPool:可缓存的线程池,该线程池中没有核心线程,非核心线程的数量为Integer.max_value,就是无限大,当有需要时创建线程来执行任务,没有需要时回收线程,适用于耗时少,任务量大的情况。
SecudleThreadPool:周期性执行任务的线程池,按照某种特定的计划执行线程中的任务,有核心线程,但也有非核心线程,非核心线程的大小也为无限大。适用于执行周期性的任务。
SingleThreadPool:只有一条线程来执行任务,适用于有顺序的任务的应用场景。
FixedThreadPool:定长的线程池,有核心线程,核心线程的即为最大的线程数量,没有非核心线程
但是不建议在生产上使用,因为在生产上一定要指定线程池的阻塞队列和拒绝策略
通过 ThreadPoolExecutor创建
public ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
七大参数
-
corePoolSize 线程池中的常驻核心线程数
创建线程池后,当有请求任务进来,就安排池中的线程去执行请求任务
当线程池中的线程数目达到 corePoolSize 后,就会把到达的任务放到缓存队列中 -
maximumPoolSize
线程池能够容纳同时执行的最大线程数,此值必须大于等于1 -
keepAliveTime 多余的空闲线程的存活时间
当前线程池数量超过 corePoolSize 时,当空闲时间达到 keepAliveTime 值时,
多余空闲线程会被销毁直到只剩下 corePoolSize 个线程为止 -
unit
keepAliveTime 的单位 -
workQueue
任务队列,被提交但尚未被执行的任务 -
threadFactory,表示生成线程池中工作线程的线程工厂<线程名字、线程序数…>,用于创建线程一般用默认的即可
-
handler,拒接策略,表示当队列满了并且工作线程大于等于线程池的最大线程数(maximumPoolSize)时,如何拒绝新的任务
线程池的执行流程
- 当调用 execute() 方法提交任务后,线程池先判断线程数是否达到了核心线程数(corePoolSize)。如果未达到线程数,则创建核心线程处理任务;否则,就执行下一步;
- 接着线程池判断任务队列是否满了。如果没满,则将任务添加到任务队列中;否则,执行下一步;
- 接着因为任务队列满了,线程池就判断线程数是否达到了最大线程数。如果未达到,则创建非核心线程处理任务;否则,就执行饱和策略,默认会抛出RejectedExecutionException异常。
拒绝策略
- AbortPolicy:不执行新任务,直接抛出异常,提示线程池已满
- DisCardPolicy:不执行新任务,也不抛出异常
- DisCardOldSetPolicy:将消息队列中的第一个任务替换为当前新进来的任务执行
- CallerRunsPolicy:直接调用execute来执行当前任务
线程池的状态
线程池状态含义如下
• RUNNING 接受新任务并且处理阻塞队列里的任务
• SHUTDOWN :拒绝新任务但是处理阻塞队列里的任务
• STOP :拒绝新任务并且放弃阻塞队列里的任务,同时会中断正在处理的任务。
• TIDYING:所有任务都执行完(包含阻塞队列里面的任务)后,当前线程池活动线程,数为0,将要调用 terminated 方法
• TERMINATED:终止状态,terminated 方法调用完成以后的状态
线程池状态转换列举如下
• RUNNING -> SHUTDOWN 显式调用shutdown () 方法 或者隐式调用了 finalize()方法里面的 shutdown() 方法
• RUNNING或SHUTDOWN -> STOP 显式调用 shutdownNow() 方法
• SHUTDOWN ->TIDYING 当线程池和任务队列都为空时
• STOP -> TIDYING 当线程池为空时
• TIDYING -> TERMNATED terminated() hook 方法执行完成
关闭线程池
- shutdown():线程池状态变为 SHUTDOWN,不会接收新任务,但已提交任务会执行完,此方法不会阻塞调用线程的执行
- shutdownNow():线程池状态变为 STOP,不会接收新任务,会将队列中的任务返回,并用 interrupt 的方式中断正在执行的任务
线程池的工作队列
- ArrayBlockingQueue:一个基于数组结构的有界阻塞队列,此队列按FIFO(先进先出)原则对元素进行排序。
- LinkedBlockingQueue:一个基于链表结构的阻塞队列,此队列按FIFO(先进先出)排序元素,吞吐量通常要高于ArrayBlockingQueue。静态工厂方法Executors.newFixedThreadPool()使用了这个队列
- SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞队列,吞吐量通常要高于LinkedBlockingQueue,静态工厂方法Executors.newCachedThreadPool()使用了这个队列。
- PriorityBlockingQueue:一个具有优先级的无限阻塞队列。
以上是关于线程池的主要内容,如果未能解决你的问题,请参考以下文章