Executor 框架的两级调度模型
在 HotSpot VM 的线程模型中,Java线程(java.lang.Thread)被一对一映射为本地操作系统线程。
在上层,Java多线程程序通常把应用分解为若干个任务,然后使用用户级的调度器(Executor 框架)将这些任务映射为固定数量的线程;在底层,操作系统内核将这些线程映射到硬件处理器上。
从图中可以看出,应用程序通过 Executor框架控制上层的调度;而下层的调度油操作系统内核控制,下层的调度不受应用程序的控制。
Executor 框架的结构与成员
Executor 框架的结构
Executor 框架主要由3大部分组成
- 任务。包括被执行任务需要实现的接口:Runnable接口或Callable接口。
- 任务的执行。包括任务执行机制的核心接口 Executor,以及继承自 Executor 的 ExecutorService 接口。Executor 框架有两个关键类实现了 ExecutorService 接口:ThreadPoolExecutor 和 SecheduleThreadPoolExecutor。
- 异步计算的结果。包括接口 Future 和实现 Future 接口的 FutureTask 类。
Executor 框架包含的主要的类有如下介绍 - Executor 是一个接口,是 Executor 框架的基础,它将任务的提交与任务的执行分离开来。
- ThreadPoolExecutor 是线程池的核心实现类,用来执行被提交的任务。
- ScheduledTheadPoolExecutor 是一个实现类,可以在给定的延迟后运行命令,或者定期执行命令
- Future 接口和实现Future 接口的 FutureTask 类,代表异步计算的结果。
- Runnable 接口和 Callable 接口的实现类,都可以被 ThreadPoolExecutor 或 ScheduledThreadPoolExecutor 执行。
主线程首先要创建实现 Runnable 或者 Callable 接口的任务对象。工具类 Executors 可以把一个 Runnable 对象封装为一个 Callable 对象(Executors.callable(Runnable task) 或 Executors.callable(Runnable task, Object resulte))。
然后可以把 Runnable 对象直接交给 ExecutorService 执行(ExecutorService.execute(Runnable command));或者也可以把 Runnable 对象提交给 ExecutorService 执行(ExecutorService.submit(Runnable task) 或 ExecutorService.submit(Callback task))。
如果执行 ExecutorService.submit,ExecutorService 将返回一个实现 Future 接口的对象。由于 FutureTask 实现了 Runnable,程序员也可以创建 FutureTask,然后直接交给 ExecutorService 执行。
最后,主线程可以执行 FutureTask.get() 方法来等待任务执行完成。主线程也可以执行 FutureTask.cancel() 来取消此任务的执行。
Executor 框架的成员
ThreadPoolExecutor
ThreadPoolExecutor 通常使用工厂类 Executors 来创建。Executors 可以创建3种类型的 ThreadPoolExecutor:
- SingleThreadExecutor 适用于需要保证顺序地执行各个任务,并且在任意时间点,不会有多个线程是活动线程的场景。
- FixedThreadPool 适用于为了满足资源管理的需求,而需要限制当前线程数量的应用场景,它适用于负载比较重的服务器。
- CachedThreadPool 是大小无界的线程池,适用于执行很多的短期异步任务的小程序,或者是负载较轻的服务器。
ScheduledThreadPoolExecutor
ScheduledThreadPoolExecutor 通常使用工厂类 Executors 来创建。Executors 可以创建2种类型的 ScheduledThreadPoolExecutor: - ScheduledThreadPoolExecutor 适用于需要多个后台线程执行周期任务,同事为了满足资源管理的需求而需要限制后台线程的数量的应用场景。
- SingleThreadScheduledExecutor 适用于需要单个后台线程执行周期任务,同时需要保证顺序地执行各个任务的应用场景。
Future接口
Future 接口和实现 Future 接口的 FutureTask 类用来表示异步计算的结果。当我们把 Runnable 接口或 Callable 接口的实现类提交给 ThreadPoolExecutor 或 ScheduledThreadPoolExecutor 时,ThreadPoolExecutor 或 ScheduledThreadPoolExecutor 会向我们返回一个 FutureTask 对象。
Runnable 接口 和 Callable 接口
Runnable 接口和 Callable 接口的实现类,都可以被 ThreadPoolExecutor 或 ScheduledThreadPoolExecuto 执行。他们之间的区别是 Runnable 不会返回结果,而 Callable 可以返回结果。提交之后返回的 FutureTask 对象,可以执行 FutureTask.get() 方法来等待任务执行完成。当任务执行完成后将返回该任务的结果。