《Java并发编程的艺术》读书笔记系列文章
思维导图
关键知识点
背景介绍
- Java 的线程既是工作单元,也是执行机制。
- 从 JDK 5 开始,把工作单元与执行机制分离开来。
- 工作单元包括
Runnable 和 Callable ,而执行机制由 Executor 框架提供。
Executor框架
两级调度模型
HotSpot VM 的线程模型中
- 底层,Java 线程(
java.lang.Thread )被一一映射为 操作系统线程。
- Java 线程启动时,创建一个本地操作系统线程。
- Java 线程终止时,这个操作系统线程也会被回收。
- 上层,Java 多线程程序把 应用 分解为 若干个任务。
- Executor 框架将这些 任务 映射为固定数量的 Java线程。
- 整体过程就是,应用 被分解为 任务 再被映射为 Java线程。
- 总结,上层的调度通过 Executor 框架控制,下层的调度由操作系统内核控制。应用 被分解为 任务 再被映射为 Java线程,最后被映射为操作系统线程。
结构与成员
框架结构
Executor 框架主要由 3 大部分组成如下:
- 任务的内容:包括被执行任务需要实现的接口,
Runnable 接口或 Callable 接口。 - 任务的执行:
Executor ,以及继承自 Executor 的 ExecutorService 接口。Executor 框架有两个关键类实现了 ExecutorService 接口(ThreadPoolExecutor 和 ScheduledThreadPoolExecutor )。 - 执行的结果:接口
Future 和实现 Future 接口的 FutureTask 类。 Executor的框架结构如图所示,执行结果分解如下:
Step 0
- 主线程首先要创建实现
Runnable 或者 Callable 接口的任务对象。 - 工具类
Executors 有两个方案把一个 Runnable 对象封装为一个 Callable 对象:Executors.callable(Runnable task) 或者 Executors.callable(Runnable task,Object resule)) 。
Step 1 把 Runnable 对象直接交给 ExecutorService 执行
- execute方式:
ExecutorService.execute(Runnable command)) - submit方式:把
Runnable 对象或 Callable 对象提交给 ExecutorService 执行
Executor-Service.submit(Runnable task) ExecutorService.submit(Callable<T> task)) ExecutorService.submit() 返回一个实现 Future 接口的对象(到目前为止的 JDK 中,返回的是 FutureTask 对象)。- 由于
FutureTask 实现了 Runnable ,也可以创建 FutureTask ,然后直接交给 ExecutorService 执行。 - 主线程执行
FutureTask.get() 方法来等待任务完成。 - 主线程执行
FutureTask.cancel(boolean mayInterruptIfRunning) 来取消此任务执行。
框架成员
ThreadPoolExecutor
使用工厂类 Executors 来创建,分三种类型。
- FixedThreadPool,使用固定线程数的线程池。适用于需要限制当前线程数量的应用场景(资源管理有需求),它适用于负载比较重的服务器。
- 使用单个线程,
|