java线程状态详解
操作系统中有比较经典的进程三态模型, 各状态之间的转换关系如下图:
类java.long.Thread
中有个内部的枚举类State
用来表示线程的状态, 它的定义如下:
public enum State {
NEW, // 刚创建, 还没启动
RUNNABLE, // 可运行状态
BLOCKED, // 阻塞态, 或被挂起
WAITING, // 等待锁的状态
TIMED_WAITING, // 等待时间的状态, 如sleep就在等待时间
TERMINATED; // 终止态
}
NEW
: 线程还没被start()
启动. 调用了start()
状态也不一定会立即改变, 中间还有一些步骤.RUNNABLE
: NEW
状态的线程start()
结束后会进入RUNNABLE
状态. 正在运行的线程一定处于RUNNABLE
状态, 使用Thread.currentThread().getState()
只会得到RUNNABLE
. 处于RUNNABLE
状态的线程并不一定在运行
. 比如当线程发生了yield()
操作时, 该线程仍然是RUNNABLE
状态, 要是对应到操作系统中的三态模型就该算是就绪
了; 再比如, 在BIO中, 线程正在网络等待时, 现成的状态仍然时RUNNABLE
, 而在底层实际上已经被阻塞了.BLOCKED
: 阻塞态, 原因通常是在等待某个锁
, 当某个synchronized
正好有线程正在使用, 另一个线程尝试进入该临界区
的时候就会被阻塞. 得到锁(比如另一个线程走完了临界区或发生了相应锁对象的wait()
操作)之后状态会由BLOCKED
恢复到RUNNABLE
.WAITING
: 这种状态通常是调用某个锁对象
的wait()
方法的结果, 类似的有Thread.join()
. 跟BLOCKED
不同, BLOCKED
是表示不能进入临界区, 所以在等待; WAITING
是已经进入了临界区, 或者可理解为已经在运行了, 然后发现缺少某些资源(锁对象), 放弃运行权, 等待资源准备好. 对某个锁对象notify()
时, 将从等待池中唤醒一个WAITING
状态的线程恢复到RUNNABLE
状态TIMED_WAITING
: 跟WAITING
不一样的地方是, WAITING
等待锁对象,它等待的是时间, 比如使用Thread.sleep()
相当于把时间资源作为所对象. 时间到达时触发线程回到工作状态.TERMINATED
: 线程结束了,run()
方法跑完了. 这是Java的一种状态,在操作系统内部可能线程已经注销了.