前文回顾
线程池里用到了阻塞队列,修改ctl状态需要一个mainLock,阻塞队列基于入队锁和出队锁,而ReentrantLock的公平锁与非公平锁都是对AQS的进一步实现,不清楚的小伙伴赶紧看看吧~
本篇文章主要讲线程池概述,力求理清相关知识点,尽量保持思路清晰,请耐心看完~
文章导读
- 线程池的继承树及相关类的介绍
- ThreadPoolExecutor的工作状态(概述,原理,转换)
- ThreadPoolExecutor的重要成员变量
- 盘点一下常见的线程池
- 总结
一、线程池的继承树及相关类的介绍
首先抛出继承关系图,打开ThreadPoolExcutor配合idea的ctrl+alt+u或ctrl+H食用最佳。
先把重要接口和类过一遍,混个眼熟。可以看出,Executor是顶级接口,ExecutorService是第一步实现,主要提供了管理线程池的方法。AbstractExecutorService的出现很容易联想到接口适配器,用于对接口抽象化。
左侧的ForkJoinPool基于工作-窃取算法是1.7开始出现的。ThreadPoolExecutor则是最常用的线程池。
下面逐个来分析一下~
Executor
线程池顶级接口,用于启动线程任务。
void execute(Runnable command);
ExecutorService
提供了线程池生命周期的管理方法
定义了线程池的状态:Running,ShuttingDown,Terminated
主要方法罗列一下:
//优雅关闭,不是强行关闭线程池,回收线程池中的资源,
//而是不再处理新的任务,将已接收的任务处理完毕后再关闭。
void shutdown();
//是否已经关闭,相当于回收了资源
boolean isShutdown();
//是否已经结束,相当于回收了资源
boolean isTerminated();
//可以提供线程执行后的返回值
Future<T> submit(Callable<T> task);
Future<?> submit(Runnable task);
ThreadPoolExecutor
最常用的线程池,除了ForkJoinPool外,其他常用线程池底层都是使用它实现的。其中FixedThreadPool,CachedThreadPool,SingleThreadPool,ScheduledThreadPool等线程池都是由它实现的,内容比较多,下一个标题讲解。
Excutors
Excutor的工具类,类似Collection和Collections的关系。
可以快速的提供若干中线程池(比如固定容量,无限容量,容量为1的线程池)。
线程池是一个进程级的重量级资源,默认生命周期和JVM一致。当开启线程池后,直到JVM关闭为止是线程池的默认生命周期。如果手工调用shutdown方法,那么线程池执行所有的任务后自动关闭。
Callable
可执行接口,类似Runnable接口,可以启动线程的接口。其中定义的方法是call。call方法的作用和Runnable中的run方法完全一致,call有返回值。
Future
代表未来,也就是线程执行结束后的一种结果,如返回值。获取执行结果的方式是通过get方法获取的。get有两个重载方法,具体的都写在下面啦。
//查看线程是否结束,call方法是否执行结束
boolean isDone();
//获取cal