前言
Java Thread类中定义了线程的整个生命周期的不同状态,一个线程在任意特定时刻只有一个状态,这些状态只是虚拟机中的状态并不能反映操作系统实际线程的状态。
线程状态
java.lang.Thread.State
中共定义了6中状态:
- NEW:线程只是完成初始化 还没启动
- RUNNABLE:线程已经准备就绪,在java虚拟机中表示线程正在执行,但在操作系统层面 线程可能还在等待比如分配CPU或IO等资源。
- BLOCKED: 此状态表示线程阻塞等待一个monitor lock进入一个
synchronized
限定的代码块或方法,或者 线程先进入synchronized
限定的方法或代码块,但是调用了wait()
方法并释放了获得的锁,
等到再次被notify()
唤醒 再次阻塞等待进入synchronized
限定的代码块或方法中。即:A、B两个线程都需要获取锁来执行方法,A获得锁还未释放,那么B就处于BLOCKED状态 - WAITING: 线程调用以下方法进入此状态:
- Object.wait() 无超时参数
- Thread.join() 无超时参数
- LockSupport.park()
线程进入此状态,等待另一个线程调用特定方法。例如:一个线程调用Object.wait()
等待另一个线程调用Object.notify()
或Object.notifyAll()
;一个线程调用了Thread.join()则等待这个线程执行完毕进入
Terminated状态
TIMED_WAITING: 线程调用以下指定等待时间等待线程的方法进入此状态:
- Thread.sleep()
- Object.wait() 带超时参数
- Thread.join() 带超时参数
- LockSupport.parkNanos()
- LockSupport.parkUntil()
TERMINATED: 线程已完成执行进入此状态
小结
我们日常工作当中经常会使用jstack
命令来分析java的堆栈信息,比如
- 当我们发现线程长时间处于BLOCKED状态,我们就需要分析下 是不是哪个地方锁没有释放?
- 如果线程处于WAITING状态,需要分析下是不是调用
Object.wait()
LockSupport.park()
的地方没有调用notify()
LockSupport.unpark()
又或是调用时机不当
学习和深入理解线程状态 对于工作中快速、精准定位问题 jstack是武功招式 线程状态可谓是内功心法。。。
附张截取网络上的线程状态转移图:
![](/Java并发/Java线程状态/java_state.png)
函数名 | JDK版本 | 消耗CPU | 能否被Interrupt | 核心方法 | 线程状态 | 备注 |
---|---|---|---|---|---|---|
Spin Lock | 1.0 | 是 | 否 | native | RUNNABLE | |
wait() | 1.0 | 否 | 是 | native | WAITING | |
LockSupport.park() | 1.5 | 否 | 是 | native | WAITING | |
sleep() | 1.0 | 否 | 是 | native | TIMED_WAITING | |
join() | 1.0 | 否 | 是 | wait() | WAITING | |
suspend() | 1.0 | 否 | 否 | native | WAITING | Deprecated |
ReentrantLock.lock() | 1.5 | 部分是 | 否 | park() | WAITING | 有可interrupt版本lockInterruptibly() |
Condition.await() | 1.5 | 否 | 是 | park() | WAITING | 有不可interrupt版本 awaitUninterruptibly() |
FutureTask.get() | 1.5 | 否 | 是 | park() | WAITING | 无 |