futuretask在jdk 7及更早版本底层基于aqs实现,通过volatile state字段、clh队列和park/unpark机制协调任务生命周期与线程阻塞唤醒,其7种状态流转均由aqs的cas操作驱动。

Java中FutureTask在JDK 7及更早版本的底层确实基于AbstractQueuedSynchronizer(AQS)实现,这是理解其线程安全与状态协调机制的关键。
核心同步结构依赖AQS
早期FutureTask将自身作为AQS的子类(或内部组合AQS实例),利用AQS提供的原子状态管理、等待队列和线程阻塞/唤醒能力。它不直接暴露AQS的acquire/release语义,而是封装为任务生命周期操作:
- state字段由AQS统一维护:volatile int state被AQS的CAS操作保护,用于表示任务所处阶段(如NEW、COMPLETING、NORMAL等)
- 等待线程被组织成CLH双向队列:当调用get()时若任务未完成,当前线程会被构造成Node节点,插入AQS同步队列尾部并挂起
- run()或cancel()触发release逻辑:任务执行结束或取消时,会调用AQS的unparkSuccessor等方法,唤醒队列头部等待线程
状态流转与AQS协作机制
FutureTask的7种状态(NEW、COMPLETING、NORMAL、EXCEPTIONAL、CANCELLED、INTERRUPTING、INTERRUPTED)全部通过AQS的state变更驱动:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 初始状态NEW对应AQS初始state=0;状态跃迁均通过compareAndSetState完成,保证可见性与原子性
- COMPLETING是过渡态,此时AQS仍处于“独占获取中”,防止并发写入outcome字段
- 进入NORMAL或EXCEPTIONAL后,AQS释放所有等待线程——本质是遍历同步队列,对每个阻塞Node调用LockSupport.unpark()
get()阻塞与awaitDone的AQS路径
调用get()时实际走的是AQS典型的acquire失败→入队→挂起流程:
- 先快速检查state是否已达终态;未完成则进入awaitDone()
- awaitDone内部构造WaitNode(轻量级Node),尝试CAS入AQS等待队列
- 入队成功后调用LockSupport.park()使线程休眠;被唤醒后再次检查state,循环直至返回结果或抛出异常
与ReentrantLock等同步器的共性
FutureTask复用了AQS的核心设计范式:
- 共享资源抽象为“任务完成状态”,而非锁或信号量
- 不使用AQS的condition queue,仅依赖sync queue实现单次通知语义(任务只完成一次)
- 取消操作cancel(true)会尝试中断runner线程,该中断动作也经由AQS协调传播到等待者
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










