并发--并发中的线程状态及不同状态下线程所在队列
Java线程有6种状态:NEW、RUNNABLE(含Ready和Running)、BLOCKED、WAITING、TIMED_WAITING和TERMINATED。线程在不同状态下会进入不同队列:就绪队列存放等待CPU的RUNNABLE线程;阻塞队列存放获取锁失败的BLOCKED线程;等待队列存放执行wait/sleep等操作的WAITING/TIMED_WAITING线程。状态转换时,被唤醒的线
一、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() 只会把线程从 等待队列 移动到 就绪队列,不直接运行。
锁释放 会把线程从 阻塞队列 移动到 就绪队列。
更多推荐
所有评论(0)