源码分析系列(一)--- 一文看懂Java中的线程池

Executors

都知道创建线程池可以使用工具类Executors,我们来看看调用Executors的方法时到底发生了什么,如果JDK提供的线程池不满足需求了,你会自己在JDK的基础上实现一个线程池吗?

从源码中可以看到调用newFixedThreadPool和newSingleThreadExecutor最终都是会创建ThreadPoolExecutor对象了,我们重要的就是研究下这个ThreadPoolExecutor了。ThreadPoolExecutor

ThreadPoolExecutor提供了四个构造方法,我们就看参数最多的那个。这里参数的含义其实也是基本上面试必问之一。

public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue

workQueue,

ThreadFactory threadFactory,

RejectedExecutionHandler handler)

先来看下下参数的含义,其实这些含义源码注释里面写的很清楚:

* @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.

超过corePoolSize数量的线程,如果在keepAliveTime时间内处于空闲时间,就会被关闭,当然会维持线程数值是corePoolSize。* @param unit the time unit for the {@code keepAliveTime} argument

keepAliveTime参数的单位

* @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

当线程数量达到线程的边界以及队列的容量时,也就是说线程池满了,应该怎么处理这个线程,可以通过handler来定义。默认是RejectedExecutionHandler,会抛出RejectedExecutionException异常线程执行流程

为了方便,我们这里就调用5个参数的构造方法,其他两个参数一般使用默认的就好了

ThreadPoolExecutor pool = new ThreadPoolExecutor(

2, //核心的线程数量2

5, //最大的线程数量5

5, //空闲数值5分钟

TimeUnit.MINUTES, //空闲时间单位分钟

new ArrayBlockingQueue

(5) //使用有界队列

);

1、线程池初始化的时候会创建工作队列,设置一些参数,但是没有立即创建工作线程:

2、提交任务到线程池,这时候就会创建工作线程了,当提交了2个任务,还没超过corePoolSize的数量,都会立即创建工作线程的。图中是有2个工作线程的情况。

3、当第三个提交任务来的时候,但是前两个线程还是忙碌,就会把任务放在队列里面,等待线程池去取任务

4、当队列满了,就会创建线程直到线程数到最大线程数。图中编号是任务的执行顺序

5、当第9个任务来的时候,因为队列已满且达到了最大线程数,所以就会执行handler指定的策略,抛出RejectedExecutionException异常。

6、如果所有线程都空闲都到达闲置时间了,就会释放线程,但是会维持corePoolSize数量的线程数。

总结

因为方便画图,这里使用的有界队列,Executors里面使用的无界队列,也就是永远都不会达到maximumPoolSize的数量,不过源码里面都是设置corePoolSize等于maximumPoolSize的,所以我们平时要自己实现线程池的时候也可以把corePoolSize和maximumPoolSize的数量设置成一致。篇幅有限,就不再详细看源码了,大家按照这个思路自己去跟下源码。希望对大家有所帮助,有帮助记得点赞哦!可以关注下,后面持续分享架构文章,谢谢!

发表评论
留言与评论(共有 0 条评论)
   
验证码:

相关文章

推荐文章

'); })();