前面几篇文章分析了线程的主要实现,今天来整体总结以下他们。
直接上总结的总览图,如下图:
如果看过前几篇文章应该基本能够看懂这张总结图,可能在单独的一篇文章里弄懂了一个知识点,但是没有一个总体的概念,所以最后有了这种总结图。前面几篇文章主要讲的就是上图中AbstractExecutorService、ThreadPoolExecutor、ScheduledThreadPoolExecutor这三个类的主要功能,因为它们是线程池真正的实现者。
接下来详细解释下上图出现的类和接口,首先是最顶层的接口Executor,它只定义了一个方法execute(Runnable command),相当于定义了一个框架,它能够执行一个任务。Executor就像是定义了一个框架,并确定了这个框架能够提供的功能。
第二个是ExecutorService接口,它继承Executor。主要扩展了关闭线程管理的一些功能,比如shutdown方法用来关闭线程池的任务,isTerminated方法来判断线程池的任务是否结束。
ExecutorService还提供了最重要的方法submit,它支持了有返回结果的任务提交,也引入了实现这个功能最关键的接口Callable、Future;
Executor、ExecutorService都是接口,只是定义了提交任务、关闭任务等方法,相当于只是申明了线程池支持这些功能。
AbstractExecutorService是线程池系列第三个类,它是抽象类并继承ExecutorService接口。它主要是实现了ExecutorService接口的submit系列方法。
实现submit方法主要依靠RunnableFuture接口和它的实现类FutureTask。RunnableFuture继承Runnable和Future接口,而它的实现FutureTask的一个属性callable是Callable类型。
FutureTask实现了Runnable的run方法,run方法调用的是callable的call方法保存执行结果。同时也实现Future的get方法获取结果,如果任务还没有执行则阻塞线程。
所以submit方法实现的主要过程是提交的任务Callable封装成FutureTask,并把FutureTask当作Runnable丢给execute方法去异步执行,然后把FutureTask当作Future作为submit返回值。
但是AbstractExecutorService并没有实现execute方法,所以它是一个抽象类,在等待有缘人来实现execute,实现线程池的最后一步。
ThreadPoolExecutor是Executor框架的正真实现者。它实现了execute方法,execute正真的实现,以下三个关键点:
HashSet<Worker> workers;//Worker集合,线程池
BlockingQueue<Runnable> workQueue;//阻塞队列,要执行的任务
final void runWorker(Worker w);//Worker调用这个方法,可以从阻塞队列中获取任务来执行。
这里有一个关键类Worker,关键源码如下:
线程池execute方法会先根据现在Worker的数量判断是创建一个Worker对象还是把任务直接放到队列中,如果新建了Worker,则在最后会调用Worker的thread的start方法,start方法会异步执行,execute方法就完成了。
start会执行thread的run方法也就会执行Worker的run方法,所以最终会执行线程池的runWorker方法,runWorker会优先执行Worker中保存的任务,如果为null则会从队列中获取任务再次执行,获取不到就阻塞。这里是一个死循环,能拿到任务就执行,执行完就再去拿,拿不到就先阻塞。
ScheduledExecutorService继承AbstractExecutorService,它申明了几个schedule开头的方法。
而ScheduledThreadPoolExecutor是ScheduledExecutorService的具体实现,通过延迟队列与线程池实现了定期执行任务的功能。
线程池一直觉得是很复杂的功能,但是分析了它主要的方法的实现后就会发现还是比较简单的,不过它的实现方式仍然是非常经典巧妙的。