一个例子讲明白线程池ThreadPoolExecutor的七大参数-----面试必考

mac2026-05-05  6

一.线程池的参数指的是什么

之前我们提到过线程池的实现类就是ThreadPoolExecutor,它是继承自AbstractExecutorService类的,实现了ExecutorService接口。

其实线程池的参数指的就是ThreadPoolExecutor的成员属性,这些属性决定了线程池本身。

二.七大参数

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {

来到ThreadPoolExecutor的构造器,发现这里的七个参数,这时候我们不明白这些都是什么含义,先上一个总结图,然后再一个一个说明:

三.一个例子

银行有很多服务窗口,有时窗口是满的,有时部分窗口休息不开放。

将整个银行看成一个线程池,每个进入的客户就是一个个任务,工作人员就是线程池中的线程,那么:

corePoolSize 核心线程数:

corePoolSize可以理解为线程池中的常驻线程数量,也就是一直在上班的员工,当调用threadPool.execute方法,这些线程就会对任务队列中的一个一个任务进行操作。

maximumPoolSize 能容纳最大线程数:

这个可以理解为银行中柜台的个数,也就是线程池中的最大容量,当所有工作人员都在柜台开始工作,此时柜台已经被占满了。

workQueue 任务队列:被提交未执行

任务队列可以理解为正在排队的客户,银行一般都有很多椅子,这就是我们的任务队列,区别在于我们是拿号按照指定次序到对应窗口,而程序中是工作线程去找任务进行执行。

任务队列的分类:

ArrayBlockingQueue 是一个基于数组结构的有界阻塞队列,此队列按 FIFO(先进先出)原则对元素进行排序。LinkedBlockingQueue 一个基于链表结构的阻塞队列,此队列按FIFO (先进先出) 排序元素,吞吐量通常要高于ArrayBlockingQueue。静态工厂方法Executors.newFixedThreadPool()使用了这个队列SynchronousQueue 一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue,静态工厂方法Executors.newCachedThreadPool(5)使用了这个队列。PriorityBlockingQueue 一个具有优先级的无限阻塞队列。

threadFactory 线程工厂:

生成工作线程的工厂对象,一般用默认的即可

handler 拒绝策略:

当队列已满,且工作线程数大于等于maximumPoolSize,此时handler会说明如何执行多出来的Runnable任务。这就相当于,当银行柜台所有员工都在上班,且椅子都满了,如何处理这个客户的请求问题。

public interface RejectedExecutionHandler { void rejectedExecution(Runnable r, ThreadPoolExecutor executor); }

其本身是一个接口,定义的方法可以看出它就是要求处理Runnable任务的。JDK有四种默认拒绝策略:

keepAliveTime & TimeUnit:

TimeUnit其实就是Java8后引入的工具类,表示时间的。keepAliveTime定义了一个时间,这个时间是用来销毁多余的工作线程的,什么是多余的工作线程呢?

对应到银行的例子,其实就是今天本来有两个员工上班(核心线程),干着干着发现客户(RunnableTask)太多,于是就会通知其他员工来上班,等到其他加班的人空闲到一定时间,就让他们回家休息,这就是keepAliveTime。

四.线程池底层原理总结:

在创建了线程池后,开始等待请求当调用execute()方法添加一个请求任务时,线程池会做出如下判断如果正在运行的线程数量小于corePoolSize,那么马上创建线程运行这个任务如果正在运行的线程数量大于或等于corePoolSize,那么将这个任务放入队列如果这个时候队列满了且正在运行的线程数量还小于maximumPoolSize,那么还是要创建非核心线程立刻运行这个任务如果队列满了且正在运行的线程数量大于或等于maximumPoolSize,那么线程池会启动饱和拒绝策略handler来执行当一个线程完成任务时,它会从队列中取下一个任务来执行当一个线程无事可做超过一定的时间(keepAliveTime)时,线程会判断: 如果当前运行的线程数大于corePoolSize,那么这个线程就被停掉。 所以线程池的所有任务完成后,它最终会收缩到corePoolSize的大小。

最新回复(0)