这个文章不会涉及太深的线程知识(太深我也不懂)。这里只是把线程池的一些概念整理一下,当被问到这个题目的时候,尽可能背给面试官听就行了。
不要问为什么,因为 JVM 就是这么设计的,要问为什么,除了设计者本人,我觉得没人能回答的更好。
为什么要有线程池
任何需要大量创建的资源,都可以通过池化技术来缓解性能问题。线程池也是这种思想,提前创建好一批线程,使用的时候直接获取线程,而不需要临时创建,销毁,提高性能。连接池,常量池也是同一种思想。使用线程池的好处有以下几点,1. 避免重复创建和销毁线程,节省资源,提高性能。2,加强对线程的管理,避免无限制的创建线程,使用线程池,可以对线程统一分配,监控。
Java 自带的线程池
在 JDK1.5 之后,Java 自带了线程池,所以不需要自己去实现。创建线程池的核心方法就是 ThreadPoolExecutor 类的构造函数。
下面的代码就是 JVM 中的源码,看看注释就行了。
Java
/**
* Creates a new {@code ThreadPoolExecutor} with the given initial
* parameters.
*
* @param corePoolSize the number of threads to keep in the pool, even
* if they are idle, unless {@code allowCoreThreadTimeOut} is set
* @param maximumPoolSize the maximum number of threads to allow in the
* pool
* @param keepAliveTime when the number of threads is greater than
* the core, this is the maximum time that excess idle threads
* will wait for new tasks before terminating.
* @param unit the time unit for the {@code keepAliveTime} argument
* @param workQueue the queue to use for holding tasks before they are
* executed. This queue will hold only the {@code Runnable}
* tasks submitted by the {@code execute} method.
* @param threadFactory the factory to use when the executor
* creates a new thread
* @param handler the handler to use when execution is blocked
* because the thread bounds and queue capacities are reached
* @throws IllegalArgumentException if one of the following holds:<br>
* {@code corePoolSize < 0}<br>
* {@code keepAliveTime < 0}<br>
* {@code maximumPoolSize <= 0}<br>
* {@code maximumPoolSize < corePoolSize}
* @throws NullPointerException if {@code workQueue}
* or {@code threadFactory} or {@code handler} is null
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
该代码注释详细的描述了构造方法的参数意义,使用的时候可查 API 文档。但是面试的时候,需要背诵记忆的。
通过线程工厂可以对线程的一些属性进行定制。
通过 ThreadPoolExecutor 类的构造方法创建线程池比较繁琐,Java 通过 Executors 提供 4 个静态方法,预设值了几种线程池。分别为:
上述就是背诵要点。具体实践的话,还是亲自写代码跑为好。