ThreadPoolExcutor 原理探究

线程池(英语:thread pool):一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络 sockets 等的数量。 例如,线程数一般取 cpu 数量 +2 比较合适,线程数过多会导致额外的线程切换开销。

Java 中的线程池是用 ThreadPoolExecutor 类来实现的. 本文就对该类的源码来分析一下这个类内部对于线程的创建, 管理以及后台任务的调度等方面的执行原理

先看一下线程池的类图:

线程池的类图

上图的目的主要是为了让大家知道线程池相关类之间的关系,至少赚个眼熟,以后看到不会有害怕的感觉。

 

Executor 框架接口

Executor 框架是一个根据一组执行策略调用,调度,执行和控制的异步任务的框架,目的是提供一种将”任务提交”与”任务如何运行”分离开来的机制。

下面是 ThreadPoolExeCutor 类图。Executors 其实是一个工具类,里面提供了好多静态方法,这些方法根据用户选择返回不同的线程实例。

ThreadPoolExcutor 原理探究

从上图也可以看出来,ThreadPoolExeCutor 是线程池的核心。

J.U.C 中有三个 Executor 接口:

Executor:一个运行新任务的简单接口;

ExecutorService:扩展了 Executor 接口。添加了一些用来管理执行器生命周期和任务生命周期的方法;

ScheduledExecutorService:扩展了 ExecutorService。支持 Future 和定期执行任务。

其实通过这些接口就可以看到一些设计思想,每个接口的名字和其任务是完全匹配的。不会因为 Executor 中只有一个方法,就将其放到其他接口中。这也是很重要的单一原则。

 

ThreadPoolExeCutor 分析

在去具体分析 ThreadPoolExeCutor 运行逻辑前,先看下面的流程图:

ThreadPoolExcutor 原理探究

该图是 ThreadPoolExeCutor 整个运行过程的一个概括,整个源码的核心逻辑总结起来就是:

创建线程:要知道如何去创建线程,控制线程数量,线程的存活与销毁;

添加任务:任务添加后如何处理,是立刻执行,还是先保存;

执行任务:如何获取任务,任务执行失败后如何处理?

下面将进入源码分析,来深入理解 ThreadPoolExeCutor 的设计思想。

 

构造函数

先来看构造函数:

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();
     // 注意 workQueue, threadFactory, handler 是不可以为null 的,为空会直接抛出错误
if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler; }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wspsys.html