Executor框架
Executor框架的两级调度模型
在HotSpot VM 的线程模型中,Java线程(java.lang.Thread)被一对一映射为本地操作系统线程,如下图。Java线程启动时会创建一个本地操作系统线程;当该Java线程终止时,这个操作系统线程也会被回收。操作系统会调度所有线程并将它们分配给可用的CPU。
在上层,Java多线程程序通常把应用分解为若干个任务,然后使用用户级的调度器(Executor框架)将这些任务映射为固定数量的线程; 在底层,操作系统内核将这些线程映射到硬件处理器上。这种两级调度模型的示意图如下:
从图中可以看出,应用程序通过Executor框架控制上层的调度;而下层的调度由操作系统内核控制,下层的调度不受应用程序的控制。
Executor框架的结构与成员
Executor框架的结构
Executor框架主要由3大部分组成:
- 任务:包括被执行任务需要实现的接口:Runnable接口或Callable接口。
- 任务的执行: 包括任务执行机制的核心接口Executor,以及继承自Executor的ExecutorService接口。 Executor框架有两个关键类实现了ExecutorService接口(ThreadPoolExecutor和ScheduledThreadPoolExecutor)。
- 异步计算的结果: 包括接口Future和实现Future接口的FutureTask类。
这些类和接口简介:
- Executor:是一个接口,它是Executor框架的基础,它将任务的提交与任务的执行分离开来。
- ThreadPoolExecutor:是线程池的核心实现类,用来执行被提交的任务。
- ScheduledThreadPoolExecutor:是一个实现类,可以在给定的延迟后运行命令,或者定期执行命令。ScheduledThreadPoolExecutor比Timer更灵活,功能更强大。
- Future接口和实现Future接口的FutureTask类,代表异步计算的结果。
- Runnable接口和Callable接口的实现类,都可以被ThreadPoolExecutor或Scheduled-ThreadPoolExecutor执行。
Executor框架的使用示意图:
- 主线程首先要创建实现Runnable或者Callable接口的任务对象。
- 把Runnable对象直接交给ExecutorService执行,ExecutorService.execute(Runnable);或者也可以把Runnable对象或Callable对象提交给ExecutorService执行ExecutorService.submit(Runnable task)或 ExecutorService.submit(Callable<T>task。
- 执行ExecutorService.submit(…),ExecutorService将返回一个实现Future接口的对象(到目前为止的JDK中,返回的是FutureTask对象)。
- 主线程可以执行FutureTask.get()方法来等待任务执行完成。主线程也可以执行FutureTask.cancel(boolean mayInterruptIfRunning)来取消此任务的执行。