Fork me on GitHub

Executor框架

注意:所有文章除特别说明外,转载请注明出处.

[TOC]

第十章 Executor框架

Java的线程既是工作单元,也是执行机制。所以在JDK 1.5 之后将工作单元和执行机制分离开,工作单元包括 Runnable 和 Callable ,执行机制由 Executor 框架提供。

Executor 管理多个异步任务的执行,而无需程序员显式地管理线程的生命周期。这里的异步是指多个任务的执行互不干扰,不需要进行同步操作。

10.1 Executor 框架简介

10.1.1 Executor 框架的两级调度模型

在上层,Java多线程程序通常将应用分解为若干个任务,然后使用用户级的调度器(Executor框架)将这些任务映射为固定数量的线程。

在底层,操作系统内核将这些线程映射到硬件处理器上。

10.1.2 Executor 框架的结构和成员

1.Executor 框架的结构

注意:Executor框架由两个关键类实现了ExecutorService接口(ThreadPoolExecutor和ScheduledThreadPoolExecutor)。

Executor 框架由3大部分组成:

1.任务:包括被执行任务需要实现的接口(Runnable接口 | Callable接口)

2.任务的执行:包括任务执行机制的核心接口Executor,以及继承Executor的ExecutorService接口。

3.异步计算的结果:包括接口Future接口和实现Future接口的FutureTask类。

Executor框架包括的主要的类和接口:

1.Executor接口:是Executor框架基础,将任务的提交与任务的执行分离开。

2.ThreadPoolExecutor线程池核心实现类:用来执行被提交的任务。

3.ScheduledThreadPoolExecutor实现类:在给定的延迟后运行命令,或者定期执行命令。

4.Future接口和实现Future接口的FutureTask类:代表异步计算的结果。

5.Runnable接口和Callable接口的实现类:可以被ThreadPoolExecutor或Scheduled-ThreadPoolExecutor执行。

任务执行过程:

1.首先主线程创建实现 Runnable 或者 Callable 接口的任务对象。工具类Executor可将一个Runnable对象封装成一个Callable对象。

2.然后可以将Runnable对象直接交给ExecutorService执行(ExecutorService.execute(Runnable command)),或者可以将Runnable对象交给 ExecutorService执行(ExecutorService.submit(Runnable task))或ExecutorService.submit(Callable task)。

3.最后主线程可以执行 FutureTask.get() 方法来等待任务执行完成。主线程也可以执行 FutureTask.cancel() 来取消任务执行。

2.Executor框架成员

1.ThreadPoolExecutor

ThreadPoolExecutor 通常使用工厂类Executors来创建。Executors可以创建3种类型的ThreadPoolExecutor。

1.FixedThreadPool

2.SingleThreadExecutor

3.CachedThreadPool

2.ScheduledThreadPoolExecutor

1.ScheduledThreadPoolExecutor:适用于需要多个后台线程执行周期任务,同时为了满足资源管理的需求而需要限制后台线程的数量的应用场景。

2.SingleThreadScheduledExecutor:适用于需要单个后台线程执行周期任务,同时需要保证顺序执行各个任务的应用场景。

3.Future接口

Future接口和实现Future接口的FutureTask类用来表示异步计算的结果。当把Runnable接口或Callable接口的实现类提交(submit)给ThreadPoolExecutor或ScheduledThreadPoolExecutor时,ThreadPoolExecutor或ScheduleThreadPoolExecutor会向我们返回一个FutureTask对象。

4.Runnable接口和Callable接口

Runnable接口和Callable接口都可以被ThreadPoolExecutor | ScheduledThreadPoolExecutor 执行,它们之间的区别在于 Runnable 不会返回结果,而Callable可以返回结果。

10.2 ThreadPoolExecutor详解

主要有是三种Executor:1.CachedThreadPool:一个任务创建一个线程。2.FixedThreadPool:所有任务只能使用固定大小的线程。3.SingleThreadExecutor:相当于大小为 1 的 FixedThreadPool。

10.2.1 FixedThreadPool详解

该线程池被称作可重用固定线程数线程池。

10.2.2 SingleThreadExecutor详解

该线程池是使用单个worker线程的Executor。

10.2.3 CachedThreadPool详解

该线程池是一个会根据需要创建新线程的线程池。

10.3 ScheduledThreadPoolExecutor详解

ScheduledThreadPoolExecutor 继承自 ThreadPoolExecutorz。其主要用来在给定的延迟之后运行任务,或者定期执行任务。其功能与Timer类似,但ScheduledThreadPoolExecutor功能更强大、灵活。Timer对应单个后台线程。

10.3.1 ScheduledThreadPoolExecutor 的运行机制

10.4 FutureTask详解

Future接口和实现了Future接口的FutureTask类,表示的是异步计算的结果。

10.4.1 FutureTask简介

FutureTask除实现Future接口之外,还是Runnable接口。所以FutureTask可以交给Executor执行,也可以调用线程直接执行(FutureTask.run())。

FutureTask可以处于以下3中状态:

1.未启动:

2.已启动:

3.已完成:

10.4.2 FutureTask的使用

可以将FutureTask交给Executor执行,或者通过ExecutorService.submit()方法返回一个FutureTask,然后执行FutureTask.get()方法或FutureTask.cancel()方法。

10.4.3 FutureTask的实现

FutureTask的实现基于 AbstractQueuedSynchronizer(AQS)。

提示:java.util.concurrent中很多阻塞类(ReentrantLock)都是基于AQS实现的。AQS 是一个同步框架,它提供通用机制来原子性管理同步状态、阻塞和唤醒线程,以及维护被阻塞线程的队列。

提示:基于AQS实现的同步器包括:ReentrantLock | Semaphore | ReentrantReadWriteLock | CountDownLatch | FutureTask。

每一个AQS实现的同步器都会包含两种类型的操作:

1.至少有一个acquire操作。该做操阻塞调用线程,直到AQS允许这个线程执行。

    FutureTask的acquire操作是:get()/get(long timeout, TimeUnit unit)方法调用

2.至少有一个release操作。该操作改变AQS的状态,改变后的状态可允许一个或多个阻塞线程被解除阻塞。

    FutureTask的release操作包括run()方法和cancel()方法

10.5 Future 模式

Future模式是多线程开发中常见的一种设计模式,核心思想是异步调用。在调用的方法返回的结果很慢的时候,我们可以让它在后台慢慢执行,我们利用这段时间处理其它任务,在真正需要数据的场合再去尝试获得需要的数据。

10.5.1 Future模式主要方法

1. boolean cancel(boolean mayInterruptIfRunning);//取消任务

2. boolean isCancelled();//是否已经取消

3. boolean isDone();//是否已经完成

4. V get() throws InterruptedException..;//取得返回对象

5. V get(long timeout, TimeUnit unit);//取得返回对象,可以设置超时时间

本文标题:Executor框架

文章作者:Bangjin-Hu

发布时间:2019年10月15日 - 09:22:26

最后更新:2020年03月30日 - 08:16:04

原始链接:http://bangjinhu.github.io/undefined/第10章 Executor框架/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

Bangjin-Hu wechat
欢迎扫码关注微信公众号,订阅我的微信公众号.
坚持原创技术分享,您的支持是我创作的动力.