FutureTask没有COMPLETED状态,合法终态仅有NORMAL和EXCEPTIONAL;其状态由volatile int state字段维护,取值0~6,对应NEW、COMPLETING、NORMAL、EXCEPTIONAL、CANCELLED、INTERRUPTING、INTERRUPTED七种状态。

FutureTask 没有 COMPLETED 状态,这是常见误解。它的合法终态只有 NORMAL(正常完成)和 EXCEPTIONAL(异常完成)。所谓“NEW 到 COMPLETED”的说法,实际对应的是 NEW → COMPLETING → NORMAL 这条主线路径。
状态字段与取值含义
FutureTask 全部状态由一个 volatile int state 字段维护,共 7 种取值(0~6),定义在源码中:
- NEW (0):任务刚创建,尚未执行
- COMPLETING (1):call() 已返回,正原子写入结果或异常(短暂过渡态,不可见于 public API)
-
NORMAL (2):成功完成,
outcome中存有返回值 -
EXCEPTIONAL (3):执行中抛出未捕获异常,
outcome中存有ExecutionException - CANCELLED (4):被取消(未启动或已启动但未完成)
- INTERRUPTING (5):正尝试中断运行中的线程
- INTERRUPTED (6):中断操作已完成
NEW → COMPLETING → NORMAL 的触发条件
这条路径代表一次成功的异步任务执行。它不靠手动设置,而由 run() 方法内部逻辑自动驱动:
- 必须调用
futureTask.run()(例如通过ExecutorService.submit()或new Thread(task).start()) - 任务需是
Callable类型,且call()方法正常返回(不抛异常) - 任务不能已被取消(
state != NEW时,run()直接退出) -
COMPLETING是 CAS 设置结果前的临界态,仅存在几纳秒;它确保outcome安全写入后再更新终态,防止并发读取到未初始化结果
为什么看不到 COMPLETING?如何验证它存在
isDone() 在 COMPLETING 时就返回 true,但 get() 仍会阻塞——因为此时 outcome 尚未写入完毕。你无法通过公开方法“看到”它,但可通过反射+延迟手段观测:
立即学习“Java免费学习笔记(深入)”;
- 自定义
FutureTask子类,重写set(V result) - 在
UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)成功后、赋值outcome前插入Thread.sleep(1) - 另起线程用反射读取
state字段,即可捕获值为1的瞬间
终态确认与结果获取
当 state >= NORMAL(即 ≥2)时,get() 才能安全返回结果或抛出异常:
-
state == NORMAL→get()返回outcome(类型已擦除,需强制转型) -
state == EXCEPTIONAL→get()抛出ExecutionException,其getCause()即原始异常 -
isDone()在NORMAL、EXCEPTIONAL、CANCELLED等终态下均返回true


















