futuretask 是 java 中实现 runnable 和 future 接口的可执行单元,封装任务执行、状态控制、结果存储与取消逻辑;它被线程池 submit 方法包装并执行,使异步任务具备开箱即用的可靠性。

FutureTask 是 Java 并发编程中连接“任务执行”和“结果获取”的关键桥梁。它不是单纯的任务容器,也不是简单的结果包装器,而是把 Runnable/Callable 任务、线程安全的状态控制、阻塞等待机制、取消逻辑和结果存储全部封装在一起的可执行单元。
FutureTask 的核心机制
它本质上是一个实现了 Runnable 和 Future 双接口的类,因此既能被线程直接执行(run()),又能被主线程用来查询状态、等待结果或取消任务。
- 状态驱动:内部用 volatile int state 控制生命周期(NEW → COMPLETING → NORMAL/CANCELLED/EXCEPTIONAL),所有状态变更都通过 CAS 保证原子性
- 结果存储:outcome 字段存放计算结果或异常,只在任务真正结束时写入一次,避免重复执行
- 等待队列:使用 WaitNode + LockSupport 实现高效的阻塞/唤醒,get() 调用时若未完成就挂起当前线程,任务结束自动唤醒所有等待者
- 取消支持:cancel(true) 尝试中断运行中的线程;cancel(false) 只拒绝尚未开始的任务,已运行的不受影响
FutureTask 与线程池的协作方式
线程池本身不直接创建 FutureTask,但它的 submit 方法会把 Callable 或 Runnable 包装成 RunnableFuture(实际就是 FutureTask),再交给 execute 执行。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 调用
executor.submit(callable)时,线程池内部调用newTaskFor(callable)创建 FutureTask 实例 - 该 FutureTask 被当作普通 Runnable 提交进工作队列,由空闲线程调用其 run() 方法执行真实逻辑
- run() 内部会捕获 call() 的返回值或异常,并通过 set()/setException() 更新 state 和 outcome
- 主线程拿到的 Future 引用,其实就是这个 FutureTask,后续所有 isDone()、get()、cancel() 都作用于它
为什么需要 FutureTask 而不只是 Future
Future 是接口,只定义了“能干什么”,比如 get()、isDone();但它不负责“怎么干”。FutureTask 才是真正干活的实现类:
- Runnable 接口让它能放进线程池执行;Future 接口让它能被主线程管理
- 没有 FutureTask,你就得自己手写状态同步、结果缓存、中断响应、异常传播等逻辑
- 它屏蔽了底层 wait/notify 或 LockSupport 的复杂性,让异步任务具备开箱即用的可靠性
典型使用场景
适合那些既要异步执行、又必须拿回结果或需精细控制生命周期的任务:
- 数据库慢查询封装为 Callable,用 FutureTask 提交后做超时 get,避免主线程卡死
- 多个并行 HTTP 请求,每个封装为 FutureTask,统一提交到线程池,再按需调用 get 获取响应
- 后台预加载资源,主线程继续渲染 UI,稍后检查 isDone() 判断是否就绪,再 get() 拿数据
- 配合 ExecutorCompletionService,优先处理最先完成的 FutureTask,实现“谁快谁先用”
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










