Java 线程有 6 种状态. 在某个给定时间点上, 一个线程只能处于这 6 种状态中的一种.
线程状态的枚举: Thread.State
这 6 种状态被明确地定义在 Thread
类的一个内部枚举类 Thread.State
中:
它们是:
NEW
(新建) A thread that has not yet started is in this state.RUNNABLE
(可运行) A thread executing in the Java virtual machine is in this state.BLOCKED
(阻塞) A thread that is blocked waiting for a monitor lock is in this state.WAITING
(等待) A thread that is waiting indefinitely for another thread to perform a particular action is in this state.TIMED_WAITING
(计时等待) A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state.TERMINATED
(终止) A thread that has exited is in this state.
注: 以上内容直接来自 State 类中的 Javadoc, 只对状态进行了翻译, 具体的描述后面再分析.
它上面还有个注解
@since 1.5
, 暗示了在 JDK1.5 时引入了这些定义.因此, 说有 6 种线程状态是对 1.5 及以后版本而言.
Thread 类中有一个方法 getState
, 返回的就是这里定义的状态.
可用于监控工具分析线程状态, 不作同步工具使用.
线程状态的监控
一些监控工具, 如 VisualVM, 如果进行了完整的 JDK 包安装, 比如在我的机器上, 可以在 C:\Program Files\Java\jdk1.7.0_25\bin
中找到它:
它有个漂亮的小图标, 可以很容易就找到它, 双击就可以打开它了:
可以看到它自身也是 Java 应用(它还能监控它自身呢), bin 下的 exe 可能仅是个引导的程序. 还有就是我们熟悉的 Eclipse 了.
界面不咋地, 一看就是典型的 Java GUI 的风格...
双击上图中本地列表下的 Eclipse, 则出现如下监控界面, 选择到"线程"的 tab 上:
上图中勾选了一个叫"Worker-JM"的线程, 可以看到它处于 WAITING 状态下, 具体在下面的 waiting on 上显示了它在一个 ArrayList 对象上等待.
注: 截图中下方的"Thread inspector"窗体是一个插件, 默认是没有安装的.
可在"菜单--工具--插件"下面找到它并安装即可.
虚拟机线程状态 vs 操作系统线程状态
首先要明确一点, 这里所谓的"Java线程状态"指的是虚拟机层面上暴露给我们的状态, 这些状态是由枚举类 Thread.State 明确定义的. 你可能听说过这样的说法, 比如在 Windows 系统下, 很多的虚拟机实现实际都把 Java 线程一一映射到操作系统的**内核线程(kernel thread)**上.
除了 1:1 映射, 还可能有 N:1 或者 N:M 映射.
总之, 世界很乱...
自然, 操作系统的线程也有它自己的状态. 你 Java 有 6 种, Windows 可能有 N 种, 到了 Linux 系统, 它可能有 M 种.
好吧, 我也不知道具体有几种~且不说操作系统各种版本满天飞.
在这里我想说的是, 你管它是 N 种还是 M 种!虚拟机层的存在, 统一了这些差别. 不管它是 N 还是 M 种, 到了 Java 层面它们都被映射到了 6 种状态上来. 自然, 两个层面上有很多状态其实是大同小异的. 至于具体差异, 那是写虚拟机实现的那些家伙们去操心的事.
有可能操作系统中的两种状态在 JVM 中则统一成了一种状态, 也可能操作系统中的一种状态在 JVM 中又细分成了两种状态, 谁知道呢? 你也不想去知道, 反正我是不想去知道.
而很多关于操作系统上的书则常会提到有 5 种**进程(process)**状态:
- new
- ready
- running
- waiting
- terminated
不幸的是, 有很多的书上常常把这些进程状态, 线程状态与 Java 线程状态混在一起谈.
这里所谓进程状态指早期的那种单线程进程的状态.
对于现在普遍的多线程进程, 显然, 谈论"进程状态"已经没有意义, 应该谈论"进程下某个线程的状态"或者直接说"线程状态".
不过有时还是会把"进程状态"和"线程状态"混着去说, 有些系统把线程叫成"轻量级进程"(light-weight process), 所以还是在谈"进程状态".
有时则甚至既不叫"进程", 也不叫"线程", 它们叫"task"或者"job".
总之还是有些乱的, 我们不妨就拿 Windows 系统为例, 用的就是"进程"和"线程"这两种较为标准的叫法, 这时一个进程下至少有一个线程, 线程是 CPU 调度的基本单位, 进程不参与 CPU 调度, CPU 根本不知道进程的存在.
你在"任务管理器"中看到的所谓"进程状态", 跟线程状态不是一回事.
至于 Java 线程的状态, 有的说有 4 种状态, 有的说有 5 种, 各种各样的说法都有.
比如看到 Java 只有 RUNNABLE(可运行的)状态, 就觉得这还不够呀, 应该还有 Running(运行中)状态;
又或者觉得 RUNNABLE 就是 Running, 所以应该还有个 Ready(就绪)状态.
如果我们读下 Thread.State
源码中的注释中, 它说得很清楚:
These states are virtual machine states which do not reflect any operating system thread states. 这些状态是虚拟机状态, 它不反映任何操作系统的线程状态.
它对应的内核线程中的状态可能有 Running 又有 Ready, 在虚拟机层面则可能统一映射成了 RUNNABLE. 如果 Java 中觉得没必要去区分这些, 我们又何必去纠结这些呢?
以 RUNNABLE 为例, 源码中的注释是这样说的: executing in the Java virtual machine(正在Java虚拟机中执行). 至于它是否真正在执行, 不是我们要操心的事.
还有的情况则比如把 Java 状态中的 BLOCKED, WAITING, TIMED_WAITING 三种状态都笼统地称为 blocked 或者 waiting.
操作系统也许只有一种状态, 但这一次, Java 作了细分, 给出了三种状态.
很多声称 Java 线程只有 4 种或 5 种状态常常都是自作主张地合并了这些状态, 把这些东西混为一谈是非常容易引发混乱的. 我们将会在后面具体地谈到.
又或者把 TIMED_WAITING 当作不存在, 从来不提有这个状态.
显然, 这种做法又是受到传统进程状态划分的影响. 尽管它与 WAITING 很像, 我们最好按着
Thread.State
中的定义来, 不要自己随意发挥.
综上所述, 为避免出现混乱, 厘清概念所处的层次是非常重要的. 如无特别说明, 讨论均在 JVM 层面上.
具体而言, 比如当说到 WAITING 状态时, 指的就是
Thread.State.WAITING
.
有了以上基础, 才能在接下来更好地去分析这 6 种状态.
具体状态分析
接下来再来细看这 6 个状态, 首先从简单的谈起.
NEW
当使用 new Thread()
创建一个新的线程, 又还没有开始执行(not yet started)它的时候就处于 NEW 状态.
这里所谓"开始执行"具体指调用线程类中的
start
方法.
注意: 你不能直接调用 run 方法, 这样的话还是在原线程上执行. 只有调用 start 方法才会开启新的执行线程, 接着它会去调用 run. 在 start 之后, 线程进入 RUNNABLE 状态, 之后还可能会继续转换成其它状态.
注: 一个线程只能被 start 一次.
TERMINATED
终止状态, 这个也没什么好说的, 完成了执行后(completed execution)或者说退出了(exited). 线程就进入了终止状态.
其它状态
余下的几个状态, 由于无法简单几句说完, 这里先作些简介:
- RUNNABLE: 前面有提到, 它指"正在 Java 虚拟机中执行".
- BLOCKED: 等待监视器锁(waiting for a monitor lock ).
这是一种特殊的 waiting, 实际上就是被 synchronized 方法或者块阻塞.
monitor 有些书上通常叫"管程", 我也不太确定要怎么叫它. 这里叫成"监视器"也是取字面的意思.
- WAITING: 无限期等待另一个线程执行一个特别的动作(waiting indefinitely for another thread to perform a particular action ).
- TIMED_WAITING: 限时等待另一个线程执行一个动作(waiting for another thread to perform an action for up to a specified waiting time ).
详细地介绍留在后面再谈.