FutureTask.get()阻塞是因为任务未完成时,线程被封装为WaitNode加入AQS等待队列,并调用LockSupport.park()挂起进入WAITING状态;带超时则进入TIMED_WAITING状态,超时后自动恢复。

FutureTask.get() 调用时,当前线程会阻塞等待任务完成,但不会改变调用线程本身的“线程状态”类别(如 RUNNABLE、WAITING 等),而是使其进入 WAITING 或 TIMED_WAITING 状态,取决于是否带超时参数。
get() 为什么会阻塞?
FutureTask 内部基于 AQS(AbstractQueuedSynchronizer)实现同步控制。当任务尚未完成(即 state
- 无参 get():调用
LockSupport.park(),线程状态变为 WAITING - 带超时的 get(long, TimeUnit):调用
LockSupport.parkNanos(),线程状态变为 TIMED_WAITING
任务完成时如何唤醒等待线程?
当 FutureTask 执行结束(正常返回或抛出异常),它会调用 finishCompletion():
- 遍历内部 waiters 栈(由 AQS 的 waiter 链表维护)
- 对每个等待线程执行
LockSupport.unpark(t) - 被唤醒的线程从 park 状态恢复,检查任务结果并返回或抛异常
注意:不是线程“切换状态类型”,而是 JVM 级别的挂起/恢复
所谓“线程状态变化”,是 JVM 线程状态机的反映,并非 FutureTask 主动修改线程状态字段:
立即学习“Java免费学习笔记(深入)”;
- 线程仍属于同一个 Thread 对象,ID 和所属线程组不变
- 操作系统层面,该线程让出 CPU,进入休眠队列;唤醒后重新参与调度
- 不会变成 BLOCKED(那是指等待进入 synchronized 块),也不是 TERMINATED
实际调试中怎么看?
可通过 jstack 或 IDE 的线程视图观察:
- 看到类似
"main" #1 prio=5 ... java.lang.Thread.State: WAITING (parking) - 堆栈中包含
java.util.concurrent.FutureTask.get(FutureTask.java:...) - 说明线程正阻塞在 get(),等待任务结果


















