- 前言:线程池存在的意义
- 线程池详解
- 线程池的优势
- 线程池的结构
- 线程池的工作原理
- 线程池生命周期
- 几种状态之间的转化过程
- 具体转化状态方法
- 线程池的几个主要参数
- Executors类提供的线程池构造方法
- java面向多线程编程时,线程创建过多,容易引发内存溢出。
- Java线程的创建、销毁和线程间切换是一件比较耗费计算机资源的。如果我们需要用多线程处理任务,并频繁的创建、销毁线程会造成计算机资源的无端浪费,因此项目中会使用是线程池技术。
- 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
- 提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
- 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,可能也会导致内存占用过多而产生OOM。
- 什么是OOM
程序申请内存过大,虚拟机无法满足我们,然后自杀了。这个现象通常出现在大图片的APP开发,或者需要用到很多图片的时候。通俗来讲就是我们的APP需要申请一块内存来存放图片的时候,系统认为我们的程序需要的内存过大,及时系统有充分的内存,比如1G,但是系统也不会分配给我们的APP,故而抛出OOM异常,程序没有捕捉异常,故而弹窗崩溃了- 为什么会有OOM?
内存泄露:申请使用完的内存没有释放,导致虚拟机不能再次使用该内存,此时这段内存就泄露了,因为申请者不用了,而又不能被虚拟机分配给别人用。(应用用的太多,并且用完没释放,浪费了。此时就会造成内存泄露或者内存溢出。)
内存溢出:申请的内存超出了JVM能提供的内存大小,此时称之为溢出。(分配的少了:比如虚拟机本身可使用的内存(一般通过启动时的VM参数指定)太少。)
- 提供更强大的功能,延时定时线程池。
- 首先来分析源码
(线程池的状态)
| 状态 | 含义 | 值 | 说明 |
|---|---|---|---|
| 状态 value 说明 | |||
| RUNNING | 当线程池创建出来的初始状态 | 111 | 能接受任务,能执行阻塞任务,能执行正在执行的任务 |
| SHUTDOWN | 调用shutdown方法 | 000 | 不接受新任务,能执行阻塞任务 ,能执行正在执行的任务 |
| STOP | 调用shutDownNow | 001 | 不接受新任务,打断正在执行的任务,丢弃阻塞任务 |
| TIDYING | 中间状态) | 010 | 任务全部执行完,活动线程也没了 |
| TERMINATED | (终结状态 | 011 | 线程池终结 |
-
解释含义
- 线程池在构造前(new操作)是初始状态,一旦构造完成线程池就进入了执行状态RUNNING。
严格意义上讲线程池构造完成后并没有线程被立即启动,只有进行“预启动”或者接收到任务的时候才会启动线程。但是线程池是出于运行状态,随时准备接受任务来执行。
-
线程池运行中可以通过 shutdown() 和 shutdownNow() 来改变运行状态
-
线程池Executor是异步的执行任务,因此任何时刻不能够直接获取提交的任务的状态。这些任务有可能已经完成,也有可能正在执行或者还在排队等待执行
1.shutdown()是一个平缓的关闭过程,线程池停止接受新的任务,同时等待已经提交的任务执行完毕,包括那些进入队列还没有开始的任务,这时候线程池处于 SHUTDOWN状态;
2.shutdownNow()是一个立即关闭过程,线程池停止接受新的任务,同时线程池取消所有执行的任务和已经进入队列但是还没有执行的任务,这时候线程池处于 STOP状态。 -
一般情况下我们认为shutdown()或者shutdownNow()执行完毕,线程池就进入TERMINATED状态,此时线程池就结束了。其实,在shutdown/stop到TERMINATED状态之间还存在一个TIDYING状态。
API
- 状态的转化关系为
调用shundown()方法线程池的状态由 RUNNING——>SHUTDOWN
调用shutdowNow()方法线程池的状态由RUNNING——>STOP
当任务队列和线程池均为空的时候 线程池的状态由STOP/SHUTDOWN——–>TIDYING
当terminated()方法被调用完成之后,线程池的状态由TIDYING———->TERMINATED状态
线程池的几个主要参数| 参数名称 | 翻译 | 解释 |
|---|---|---|
| corePoolSize | 核心线程池大小) | 核心线程池大小, 新的任务到线程池后,若线程池已创建的线程数小于corePoolSize,即便存在空闲线程,线程池会创建新的线程,直到核心线程池已满。 |
| maximumPoolSize | 最大线程池大小 | 线程池所允许的最大线程个数。当队列满了,且已创建的线程数小于maximumPoolSize,则线程池会创建新的线程来执行任务。另外,对于无界队列,可忽略该参数。 |
| keepAliveTime | 线程保持存活时间 | 当线程池中线程数大于核心线程数时,线程的空闲时间如果超过线程存活时间,那么这个线程就会被销毁,直到线程池中的线程数小于等于核心线程数。 |
| unit | 参数的时间单位 | 线程存活时间的单位 |
| workQueue | 任务队列 | 用于传输和保存等待执行任务的阻塞队列。 |
| threadFactory | 线程工厂 | 创建新线程。主要用于给任务线程起个自定义名字 |
| handler | 线程饱和策略 | 当线程池和队列都满了,再加入线程时会执行此策略。 |
- newCachedThreadPool
- newFixedThreadPool
- newScheduledThreadPool
- newSingleThreadExecutor



