一、开篇
线程池、数据库连接池,在平时的学习中总能接触到这两个词,但它们到底是什么?和线程,数据库连接有什么关系?为什么需要“池”?“池”的概念及作用是什么?要弄清楚这些问题,就要深入到“池”的实现中去。
之前找实习工作时,时常有面试官问这类问题,自己平时知道如何使用Java的Executor线程池框架,但是具体的细节还真没感受,所以打算开始试着研究一下Executor线程池框架。
废话到此打住,正式开始!
二、Executor整体框架
让我们先站在一个较高的角度俯视一下Java线程池的整体结构,在了解了结构的基础上去专研细节,这样学习起来清晰明了,目的性强。首先给出整体框架图,然后解释各个部分的作用:
图片来源:http://www.blogjava.net/xylz/archive/2010/12/21/341281.html(这是一个将线程池比较优秀的blog,强烈推荐!)
Executor:它解决了线程次处理任务的入口问题,后面会讲到线程池会在这里面实现线程调度的重要逻辑,比如是创建一个新线程来处理任务还是重用线程池中的线程或者拒绝任务等等
ExexutorService:这个接口继承了Executor接口并增加了向线程池提交任务(submit)、管理线程池的方法(showdown,showdownNow),平时我们使用线程池大多也是使用这个接口里定义的方法。
ScheduledExecutorService:这里面主要实现的延时或周期任务的管理,类似于Timer、TimerTask。
Callable:Thread的基础知识,构建出的线程在执行完后可以获取到执行结果。
Future:任务管理和结果获取,通过它可以取消一个任务的执行,或者在任务执行完成后获取结果
CompletionService和ExecutorCompletionService:一个用来处理短暂任务组的轻量线程框架,后面会有专门讲这个的部分。
ThreadPoolExecutor:线程池的默认实现。
ScheduledThreadPoolExecutor:调度线程池的默认实现。
Executors:提供了一系列生成线程池的工厂方法:
- newSingleThreadExecutor:创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
- newFixedThreadPool:创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。
- newCachedThreadPool:创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。
- newScheduledThreadPool:创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。
- newSingleThreadScheduledExecutor:创建一个单线程的线程池。此线程池支持定时以及周期性执行任务的需求。
有了大体认识后,后面我们就开始研究各个细节部分。