简介
线程池”,顾名思义就是一个线程缓存。线程是稀缺资源,如果被无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,因此Java中提供线程池对线程进行统一分配、调优和监控。
优势
池化技术相比大家已经屡见不鲜了,线程池、数据库连接池、Http 连接池等等都是对这个思想的应用。池化技术的思想主要是为了减少每次获取资源的消耗,提高对资源的利用率。
线程池的好处有:
- 复用存在的线程,减少线程创建,销毁的开销,提高性能
- 提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。
- 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
使用场景
- 单个任务处理时间比较短
- 需要处理的任务数量很大
线程池一般用于执行多个不相关联的耗时任务,没有多线程的情况下,任务顺序执行,使用了线程池的话可让多个不相关联的任务同时执行以提高效率。
假设我们执行n个不相关的耗时任务如下图可以提高执行效率

Executor 框架
简介
Executor框架是 Java5 之后引进的,其内部使用了线程池机制,通过该框架来控制线程的启动、执行和关闭。
通过 Executor 来启动线程比使用 Thread 的 start 方法更好,除了更易管理,效率更好(用线程池实现,节约开销)外,还有关键的一点:有助于避免this逃逸问题[^RUNOOB]。
补充:this 逃逸是指在构造函数返回之前其他线程就持有该对象的引用. 调用尚未构造完全的对象的方法可能引发令人疑惑的错误。
Executor框架不仅包括了对线程池的管理,还提供了线程工厂、任务队列以及拒绝策略等,Executor 框架让并发编程变得更加简单。
框架结构
任务(Runnable/Callable)
任务,也就是工作单元,执行的任务需要实现Runnable接口或者Callable接口
任务的执行(Executor)
把任务分派给多个线程的执行机制,包括Executor接口及继承自Executor接口的ExecutorService接口。ThreadPoolExecutor 和 ScheduledThreadPoolExecutor 这两个关键类实现了 ExecutorService 接口。
我们主要关注ThreadPoolExecutor这个类。这个类在实际使用线程池中的频率是非常高的, 类图如下

异步执行结果(Future)
Future 接口以及 Future 接口的实现类 FutureTask 类都可以代表异步计算的结果。
当我们把 Runnable接口或Callable接口的实现类提交给 ThreadPoolExecutor 或 ScheduledThreadPoolExecutor 执行。(调用 submit() 方法时会返回一个 FutureTask 对象)
Executor 使用示意图

- 主线程创建实现 Runnable 或者 Callable 接口的任务对象。
- 将上一步的对象交给 ExecutorService 执行 ExecutorService.execute(Runnable command) 或者 ExecutorService.submit(Runnable task) 和 ExecutorService.submit(Callable
task) - 如果上步骤执行的是 ExecutorService.submit() 方法将异步返回一个 FutureTask对象,这也是submit 和 execute执行任务的区别。
- 主线程可以执行 FutureTask.get() 方法来等待任务执行完成。主线程也可以执行 FutureTask.cancel(boolean mayInterruptIfRunning)来取消此任务的执行。
ThreadPoolExecutor 类简单使用
线程池实现类 ThreadPoolExecutor 是 Executor 框架最核心的类。
ThreadPoolExecutor 源码解析
后期单独进行讲解
若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏
扫描二维码,分享此文章