线程池的优势
通常我们在需要一个新的线程时,就会去创建一个线程,通常都会使用继承Thread类或者实现Runnable的方法来创建新的线程,这样的方式代码实现简单。但是当我们处于一个高并发的环境下时,这样的方法有时会遇到很尴尬的情况。比如:如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。为了个别很简单的任务去不断的创建和删除新的线程,消耗的时间成本是很不值得的。
于是Java的线程池的优势便在这个时候体现出来了。线程池创建出一批新的线程,分别执行不同的任务,执行完各自的任务后不会被销毁,而是继续用于执行其他的任务。
除此之外,线程池还可以根据服务器情况,通过参数调节线程的数量,让服务器达到一个比较健康的运行状况。
总结:
-
线程是稀缺资源,使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以重复使用。
-
可以根据系统的承受能力,调整线程池中工作线程的数量,防止因为消耗过多内存导致服务器崩溃。
线程池的创建及参数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler)
corePoolSize:线程池核心线程数量,也可以称为最小线程数,意为在池中保持的线程的最小数量。
maximumPoolSize:线程池能容纳的最大线程数量。
keepAliverTime:当活跃线程数大于核心线程数时,空闲的多余线程最大存活时间。
unit:存活时间的单位。
workQueue:存放任务的队列。
handler:拒绝任务处理器,超出线程范围和队列容量的任务的处理程序。
线程池的线程添加策略
在面试一定会遇到比较实际的问题比如向一个corePoolSize为10的线程池中添加一个任务将会发生什么。这里就来说一下线程池在不同情况下的添加策略。
设线程池中的线程数为n,当一个任务被添加到线程池时:
- 如果此时n < corePoolSize, 不管线程池中是否有空余线程,都会创建新的线程直到n = corePoolSize.
- 如果此时n = corePoolSize, 而workQueue还没有满,则将任务添加到workQueue中。
- 如果此时n > corePoolSize, 而workQueue已满,则将增加线程池中的线程数量直到n = maximumPooleSize.
- 如果此时n > corePoolSize, 而workQueue已满,n = maximumPoolSize。则通过handler所指定的策略处理此任务。
- 如果此时n > corePoolSize,某线程空闲时间超过 keepAliveTime,则该线程会被终止。