线程池ThreadPoolExecutor源码解析

Posted 松然聊技术

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程池ThreadPoolExecutor源码解析相关的知识,希望对你有一定的参考价值。

张强,16年加入京东,目前就职于京东商城京麦平台组,从事京东对外开放平台和服务于第三方入驻商家的相关工作,开源爱好者,对常用开源框架如Spring、Mybatis、Dubbo等有源码级别的了解,热衷于研究各种技术,致力于成为一名有腔调的工程师


正文


我们在使用线程池的时候,可以使用Executors工厂类来创建线程池,或者是直接使用构造方法创建,我们首先来看一下ThreadPoolExecutor的构造方法: ThreadPoolExecutor:

我们来解释一下构造方法中这些参数的作用:

  • corePoolSize:当我们向线程池中提交任务时,线程池会创建一个新线程来执行任务,直到当前线程数等于corePoolSize,这时后面再次提交的任务会被保存到阻塞队列中,等待被执行。如果执行了线程池的prestartAllCoreThreads()方法,线程池会提前创建并启动所有核心线程

  • maximumPoolSize:线程池线程数量的最大上限,如果当前阻塞队列满了,且继续提交任务,则创建新的线程执行任务,前提是当前线程数小于maximumPoolSize

  • keepAliveTime:线程空闲时的存活时间,即当线程没有任务执行时,继续存活的时间,默认情况下,该参数只在线程数大于corePoolSize时才有用

  • unit:是keepAliveTime的时间单位

  • workQueue:任务存储的队列,用来保存等待被执行的任务的阻塞队列,在JDK中提供了如下阻塞队列:

  • ArrayBlockingQueue:基于数组结构的有界阻塞队列,按FIFO排序任务

  • LinkedBlockingQuene:基于链表结构的阻塞队列,按FIFO排序任务,吞吐量通常要高于ArrayBlockingQuene

  • SynchronousQuene:一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQuene

  • priorityBlockingQuene:具有优先级的无界阻塞队列

  • threadFactory:创建线程的工厂,默认为Executors.DefaultThreadFactory,里面定义了线程计数,并且给生产的线程命名(pool-线程池号-thread-线程号),可以自定义,实现ThreadFactory重写newThread方法

  • handler:饱和策略,可以自定义,实现RejectedExecutionHandler重写rejectedExecution方法

  • AbortPolicy:默认饱和策略,直接抛出一个RejectedExecutionException异常,让调用者自己处理

  • DiscardPolicy:后续的任务都抛弃掉

  • DiscardOldestPolicy:会将等待队列里最旧的任务踢走,让新任务得以执行

  • CallerRunsPolicy:它既不抛弃新任务,也不抛弃旧任务,而是直接在当前线程运行这个任务,当前线程一般就是主线程,主线程运行任务,有可能会阻塞,推荐少用

下面我们来看一下我们为线程池提交任务时使用的execute方法: ThreadPoolExecutor:

线程池ThreadPoolExecutor源码解析

这里翻译一下方法中给出的注释:



分三步进行:

  • 如果少于corePoolSize线程正在运行,尝试使用给定命令作为第一个任务启动一个新线程,对addWorker的调用以原子方式检查runState和workerCount,返回false防止错误报警在不应该增加时增加线程

  • 如果任务可以成功排队,那么我们仍然需要二次检查是否应该添加一个线程(因为现有的线程自上次检查以来已经死掉)或者自进入此方法后关闭了该线程。 所以我们重新检查状态,如果有必要的话回滚队列,如果没有的话,就开始一个新的线程

  • 如果我们不能排队任务,那么我们尝试添加一个新线程。 如果失败,我们知道我们已关闭或饱和,因此拒绝任务



我们用一张图来表示这个过程,这张图是网上找的,可以很清晰的表示这个过程: 

方法里我们看到获取线程池的运行状态和线程数量都和一个叫做ctl的变量有关,我们来分析一下这个变量 ......


------> 内容过长,请点击阅读原文


以上是关于线程池ThreadPoolExecutor源码解析的主要内容,如果未能解决你的问题,请参考以下文章

线程池(ThreadPoolExecutor)源码解析

Java Executor源码解析—ThreadPoolExecutor线程池其他方法的源码

线程池技术之:ThreadPoolExecutor 源码解析

Java Executor源码解析—ThreadPoolExecutor线程池execute核心方法源码一万字

线程池ThreadPoolExecutor——Worker源码解析

Java Executor源码解析—ThreadPoolExecutor线程池submit方法以及FutureTask源码一万字