前言
多线程一直是Java进阶的必修课,在Java中,我们很早就知道可以通过线程类和运行的接口来实现多线程。与之有着类似职责的数据库连接,也可通过JDBC创建与使用。但我们深知无论是数据库连接的创建与销毁,还是线程的创建与销毁,都是一件及其消耗性能的事情。为了减少这种情况的发生,前辈们就在思考,是不是可以复用已有的数据库连接?减少创建,销毁动作吗?这就是后来数据库连接池的由来。同样的,为了复用线程,也就有了线程池。我一直独自暗喜,身为一位幸福的Java程序员,前有Java虚拟机管理内存,后有Doug Lea大师提供并发库,锁机制。简直幸福的不像话,不过幸福归幸福,该掌握的还是需要掌握的,我们一起来看看今天的主角:ThreadPoolExecutor。
简介
在面试过程中,也时常会遇到一些关于线程池的问题,例如:
- <李>
线程池中核心参数有哪些?
李> <李>有没有自己实现过线程池吗?
李> <李>如果让你自己实现线程池,你会怎么做?
李>…
这些问题,其实考核的就是Java线程池的知识,更具体一点就是对ThreadPoolExector类熟不熟悉,下面代码是ThreadPoolExector类的全参构造函数。下面我们就一一对参数进行了解。
<代码>公共ThreadPoolExecutor (int corePoolSize,
int maximumPoolSize长keepAliveTime
,
TimeUnit unit,
BlockingQueue工作队列,ThreadFactory ThreadFactory
,
RejectedExecutionHandler处理程序){
如果corePoolSize & lt;0 | |
maximumPoolSize & lt;=0 | |
maximumPoolSize & lt;corePoolSize | |
keepAliveTime & lt;0)
把新IllegalArgumentException ();
如果(工作队列==null | | threadFactory==null | |处理==null)
抛出NullPointerException ();
。corePoolSize=corePoolSize;
。maximumPoolSize=maximumPoolSize;
。工作队列=工作队列;
。keepAliveTime=unit.toNanos (keepAliveTime);
。threadFactory=threadFactory;
。处理程序=处理程序;
} 代码>
其中:
- <李>
corePoolSize:表示该线程池最小的工作线程数。默认情况下,当需要使用时创建线程,也可以调用prestartAllCoreThreads()方法进行预创建所有的核心线程。
李> <李>maximumPoolSize:表示该线程池最大的线程数量,理论上将其设置为无限大,就会创建无限多的线程,当然,创建线程的数量最终由系统资源也就是操作系统决定。
李> <李>keepAliveTime:表示空闲线程的超时时间,(单位为纳秒)。但在构造函数中,单位与单位参数配合使用,最终转换为纳秒。
李> <李>单元:表示空闲线程超时的时间单位,可选值有:java.util.concurrent.TimeUnit中的值,秒(秒)分钟(分)小时(小)时,天(天)等。
李> <李>工作队列:表示工作队列(其实是一个可运行队列,在线程池中定义为工人),其基类为:java . util . concurrent。李BlockingQueue .
> <李>threadFactory:线程工厂,通常用于创建线程,以及命令规则。默认为:Executors.defaultThreadFactory ()。
李> <李>处理程序表示处理策略,当工作队列队列满时,以及创建线程错误时的处理策略。其基类为java . util . concurrent。RejectedExecutionHandler。默认为:AbortPolicy策略。
李>不同组合
在java . util . concurrent。执行人类为我们提供了多种组合,其底层还是调用ThreadPoolExecutor。下面列举几个常用的方法:
<强> newFixedThreadPool 强>
<代码>公共静态ExecutorService newFixedThreadPool (int nThreads) {
返回新ThreadPoolExecutor (nThreads nThreads,
0 l, TimeUnit。毫秒,
新LinkedBlockingQueue());
}
…代码>
<强>特性强>:线程数量大小固定,且corePoolSize与maximumPoolSize数量相等。当线程数量设置太少时.task则会积压在LinkedBlockingQueue队列中。当任务任务大于整数。MAX_VALUE时则会有伯父发生的风与之类是的还有newSingleThreadExecutor方法。
<强> 2。newCachedThreadPool 强>
<代码>公共静态ExecutorService newCachedThreadPool () {
返回新ThreadPoolExecutor(0,整数。MAX_VALUE,
60 l, TimeUnit。秒,
新SynchronousQueue());
} 代码>
<强>特性强>:corePoolSize数量为0,maximumPoolSize数量为Integer.MAX_VALUE,也就是说理论上是可以创建整数。MAX_VALUE个线程的.keepAiveTime时间为60秒.BlockingQueue使用的是SynchronousQueue,由于其没用容量,意味这每一次把对应着一次把操作,其吞吐量比较高。正因为如此,当任务到达一定程度时,可能会创建许多线程,从而导致伯父,甚至服务不可用。