1. 概述

FutureTask 是一个可取消的、异步执行任务的类,它的继承结构如下:

它实现了 RunnableFuture 接口,而该接口又继承了 Runnable 接口和 Future 接口,因此 FutureTask 也具有这两个接口所定义的特征。FutureTask 的主要功能:

  1. 异步执行任务,并且任务只执行一次;
  2. 监控任务是否完成、取消任务;
  3. 获取任务执行结果。

下面分析其代码实现。

2. 代码分析

2.1 RunnableFuture 接口

分析 FutureTask 的代码之前,先看下它实现的接口。RunnableFuture 接口定义如下:

public 

RunnableFuture 接口继承了 Runnable 接口和 Future 接口,而 Runnable 接口只有一个 run 方法,这里不再赘述。下面分析 Future 接口。

2.2 Future 接口

Future 接口方法定义如下:

主要方法分析:

/*

2.3 FutureTask 代码分析

  • 任务的状态变量
// 任务的状态

其中 state 表示任务的状态,总共有 7 种,它们之间的状态转换可能有以下 4 种情况:

  1. 任务执行正常:NEW -> COMPLETING -> NORMAL
  2. 任务执行异常:NEW -> COMPLETING -> EXCEPTIONAL
  3. 任务取消:NEW -> CANCELLED
  4. 任务中断:NEW -> INTERRUPTING -> INTERRUPTED

示意图:

  • WaitNode 类

在分析其他成员变量之前,先看一个内部嵌套类 WaitNode:

static 

代码比较简单,就是对 Thread 的封装,可以理解为单链表的节点。

  • 其他成员变量
/** The underlying callable; nulled out after running */

其中 waiters 是一个 Treiber 栈,简单来说,就是由单链表组成的线程安全的栈,如图所示:

  • 构造器
// 创建一个 FutureTask 对象,在运行时将执行给定的 Callable

这两个构造器分别传入 Callable 对象和 Runnable 对象(适配为 Callable 对象),然后将其状态初始化为 NEW。

  • run: 执行任务
public 

  • set & setException: 更新状态值,唤醒栈中等待的线程
protected 

这两个方法的操作类似,都是更新 state 的值并给返回结果 outcome 赋值,然后执行结束操作 finishCompletion 方法:

private 

finishCompletion 方法的作用就是唤醒栈中所有等待的线程,并清空栈。其中的 done 方法实现为空:

protected 

子类可以重写该方法实现回调功能。

  • get: 获取执行结果
// 获取执行结果(阻塞式)

这两个方法都是获取任务执行的结果,原理也基本一样,区别在于后者有超时等待(超时会抛出 TimeoutException 异常)。

  • awaitDone: 等待任务执行完成
// Awaits completion or aborts on interrupt or timeout.

该方法的主要判断步骤如下:

  1. 若线程被中断,则响应中断;
  2. 若任务已完成,则返回状态值;
  3. 若任务正在执行,则让出 CPU 时间片;
  4. 若任务未执行,则将当前线程封装为 WaitNode 节点;
  5. 若 WaitNode 未入栈,则执行入栈;
  6. 若已入栈,则将线程挂起。

以上步骤是循环执行的,其实该方法的主要作用就是:当任务执行完成时,返回状态值;否则将当前线程挂起。

  • removeWaiter: 移除栈中的节点
private 

  • report 方法:封装返回结果
private 

该方法就是对返回结果的包装,无论是正常结束或是抛出异常。

  • cancel: 取消任务
public 

3. 场景举例

FutureTask 适合多线程执行一些耗时的操作,然后获取执行结果。下面结合线程池简单分析其用法,示例代码如下(仅供参考):

public 

4. 小结

FutureTask 是一个封装任务(Runnable 或 Callable)的类,可以异步执行任务,并获取执行结果,适用于耗时操作场景。

参考链接:

FutureTask源码分析 - 代码星冰乐​www.hchstudio.cn

人类身份验证 - SegmentFault​segmentfault.comJava的Future机制详解​www.jianshu.com

futuretask使用_JDK源码分析-FutureTask相关推荐

  1. java futuretask 源码解析_Java异步编程——深入源码分析FutureTask

    Java的异步编程是一项非常常用的多线程技术. 之前通过源码详细分析了ThreadPoolExecutor<你真的懂ThreadPoolExecutor线程池技术吗?看了源码你会有全新的认识&g ...

  2. JDK源码分析 FutureTask源码分析

    文章目录 前言 一.Callable接口 二.Future接口 三.FutureTask源码分析 3.1 Future继承结构图 3.2 参数介绍 3.3 构造函数 3.4. FutureTask的A ...

  3. 线程池源码分析-FutureTask

    1 系列目录 线程池接口分析以及FutureTask设计实现 线程池源码分析-ThreadPoolExecutor 该系列打算从一个最简单的Executor执行器开始一步一步扩展到ThreadPool ...

  4. c++ vector拷贝构造_JDK源码分析-Vector

    1. 概述 上文「JDK源码分析-ArrayList」主要分析了 ArrayList 的实现原理.本文分析 List 接口的另一个实现类:Vector. Vector 的内部实现与 ArrayList ...

  5. Java并发编程笔记之FutureTask源码分析

    FutureTask可用于异步获取执行结果或取消执行任务的场景.通过传入Runnable或者Callable的任务给FutureTask,直接调用其run方法或者放入线程池执行,之后可以在外部通过Fu ...

  6. FutureTask源码分析

    2019独角兽企业重金招聘Python工程师标准>>> 在JCU中,FutureTask是Future的具体实现,且实现了Runnable接口,即FutureTask满足了Task的 ...

  7. java futuretask 源码_java并发编程——FutureTask源码分析

    FutureTask的简单示例: FutureTask的应用场景,如果在当前线程中需要执行比较耗时的操作,但又不想阻塞当前线程时,可以把这些作业交给FutureTask,另开一个线程在后台完成,当当前 ...

  8. java实现多线程的方式并源码分析

    个人资源与分享网站:首页-小草资源分享网站 方式一:继承Thread 定义一个MyThread类,重写run方法 public class MyThred extends Thread{ @Overr ...

  9. ExecutorCompletionService 源码分析

    概要 在ExecutorService的submit方法中可以获取返回值,通过Future的get方法,但是这个Future类存在缺陷,Future接口调用get()方法取得处理后的返回结果时具有阻塞 ...

最新文章

  1. 使用Leangoo共享脑图/思维导图做多级需求管理
  2. 健康饮食动起来[我写绿色IT]
  3. kubernetes入门指南(一)
  4. 基础的VueJS面试题(附答案)
  5. Adobe Acrobat Pro设置高亮快捷键
  6. Python疑难杂症:SyntaxError: Non-ASCII character Python中文处理问题
  7. matplotlib绘图进阶
  8. 破解wifi时遇到rtl8187 - [phy1]SIOCSIFFLAGS: Name not unique on network
  9. 谷歌浏览器上传下载奔溃问题解决方法
  10. C++控制输出对齐---setw()函数
  11. C#实现百度翻译功能
  12. 网络教育本科统考计算机和英语作文,远程教育本科统考英语真题及答案
  13. oCPC实践录 | oCPC产品设计与出价原理(1)
  14. 【Java】——命名规范
  15. Appium+python(1):python运行真机App程序示例
  16. 这么多处理器(CPU/SOC)牌子,到底哪家强
  17. 《满江红》非岳飞所作?
  18. 数据库的行列互换问题
  19. 常用SQL语句大全实例总结-基础篇
  20. 中国数字银行春季论坛热议高质量发展 金融科技破解资产负债管理难题

热门文章

  1. python使用imbalanced-learn的BorderlineSMOTE方法进行上采样处理数据不平衡问题
  2. Numpy的广播机制详解(broadcasting)
  3. java常用注解汇总_Spring常用注解汇总
  4. LoRDEC:hybrid correction of long reads 长读的混合校正
  5. 深圳大学计算机暑期学校,The First Day-深度学习暑期学校
  6. 排班系统c语言设计说明,帮我设计一个关于员工排班的C语言程序
  7. 五、线程的概念和特点
  8. Node.js 报语法错误 SyntaxError: Unexpected identifier
  9. 深度学习:知识回收(Lecture3+4 PLA+Decision Tree)
  10. gcc8之前,coredump文件无法显示正确的函数调用栈信息