并发--并发中的线程状态及不同状态下线程所在队列
一、Java 线程的几种状态(
Thread.State
)在 Java 中,线程有以下几种状态(
java.lang.Thread.State
枚举):
NEW(新建)
线程对象被创建,但还没有调用
start()
方法。不会进入调度队列。
RUNNABLE(可运行)
线程已经调用了
start()
,等待 CPU 调度。这里的 RUNNABLE 包含:
Ready(就绪):在 就绪队列(Ready Queue) 中,等待 CPU 时间片。
Running(运行中):正在占用 CPU 执行。
BLOCKED(阻塞)
线程在等待获取某个 对象锁(monitor)。
出现场景:
synchronized
进入临界区失败。所在队列:锁的 EntryList(阻塞队列)。
WAITING(无限期等待)
线程主动进入等待状态,直到被其他线程显式唤醒。
出现场景:
Object.wait()
(无超时)
LockSupport.park()
所在队列:对象的 WaitSet(等待队列)。
TIMED_WAITING(限期等待)
和 WAITING 类似,但有超时时间。
出现场景:
Thread.sleep(timeout)
Object.wait(timeout)
join(timeout)
LockSupport.parkNanos()
/parkUntil()
所在队列:等待队列(WaitSet),带超时。
TERMINATED(终止)
线程执行完毕,生命周期结束,不会再进入任何队列。
二、线程在不同状态下的队列位置
就绪队列(Ready Queue)
存放处于 RUNNABLE-Ready 的线程。
等待 CPU 调度。
特点:只有获得 CPU 时间片的线程才能进入 Running。
阻塞队列(EntryList / Contention Queue)
存放 BLOCKED 状态线程。
线程因获取不到锁而阻塞。
一旦锁被释放,JVM 会从该队列中唤醒一个或多个线程,进入就绪队列(不是立即运行)。
等待队列(WaitSet)
存放 WAITING / TIMED_WAITING 状态的线程。
线程主动调用
wait()
/join()
/sleep()
进入。必须通过
notify()
/notifyAll()
/ 超时 才能退出。被唤醒后不会直接运行,而是进入 就绪队列 等待 CPU。
三、状态与队列的对应关系
状态 触发条件 所在队列 退出方式 NEW new Thread() 无 调用 start()
→ 就绪队列RUNNABLE (Ready) start() 后 / 被唤醒 就绪队列 CPU 调度 → Running RUNNING CPU 时间片分配 CPU 时间片完 / 阻塞 / 等待 BLOCKED 申请锁失败 阻塞队列(EntryList) 锁释放后 → 就绪队列 WAITING wait() / park() 等待队列(WaitSet) notify() / unpark() → 就绪队列 TIMED_WAITING wait(timeout) / sleep(timeout) 等待队列(WaitSet) 超时 / notify() → 就绪队列 TERMINATED run() 执行结束 无 生命周期结束
四、关键点总结
就绪队列:存放所有等待 CPU 的线程。
阻塞队列:存放获取不到锁的线程。
等待队列:存放执行
wait()
/sleep()
/join()
等等待操作的线程。notify()/notifyAll() 只会把线程从 等待队列 移动到 就绪队列,不直接运行。
锁释放 会把线程从 阻塞队列 移动到 就绪队列。