题目
Java 线程有哪些状态(生命周期)
答案
线程的六种状态在以及各种状态之间的转换操作在 Thread 类中写得非常清楚:

各状态的转换图如下:

> 比较重要的其实就是图中我框出来的 3 个地方
下面详细分析:
1)`NEW`:初始状态,线程被创建出来但是还没有开始运行,也就是还没有调用 start 方法
2)`RUNNABLE`:当调用了 start 方法后,线程就进入了运行状态(RUNNABLE ),Java 线程将操作系统中线程的就绪(READY)和运行(RUNNING)两种状态统称为 “RUNNABLE”。
> 回顾下操作系统中经典的线程五态模型:
>
> 
3)`BLOCKED`:阻塞状态,表示线程阻塞于锁。
从 Thread 类的源码注释中我们可以看出,这个锁指的是 `monitor` 锁,即 `synchronized`。
就是说当线程试图获取 `synchronized` 锁住的对象的时候,**如果竞争锁失败了,那么这个线程就进入 BLOCKED 态**。
当持有该对象锁的线程的 `synchronized` 代码块执行完毕的时候,会唤醒该对象上所有 BLOCKED 的线程(BLOCKED 队列)重新竞争,如果其中 t 线程竞争成功,那么 t 线程就会从 BLOCKED 状态进入 RUNNABLE 状态 ,而其它竞争失败的线程仍然处于 BLOCKED 状态。
> 不同于 synchronized 锁的是,阻塞在 J.U.C 的 Lock 接口下的锁的线程状态并不是 BLOCKED 态,因为 Lock 接口对于阻塞的实现均使用了 LockSupport 类中的相关方法。从上面的转换图中可以看出,阻塞在 Lock 接口的线程状态是 WAITING 状态
4)`WAITNG`:等待状态,进入等待状态的线程需要依靠其他线程的通知才能够返回到 RUNNABLE 状态。
从 Thread 类的源码注释以及图片中可以看出来,线程从 RUNNABLE 到 WAITING 状态的转换有 3 种场景:
- 调用了 `Object.wait`
- 调用了 `Thread.join`
- 调用了 `LockSupport.park` 暂停线程
另外,线程从 WAITING 状态回到 RUNNABLE 的场景,从源码注释中同样也可以很清楚的看出来:
- 调用了 `Object.notify`
- 调用了 `Object.notifyAll`
- 调用了 `LockSupport.unpark` 恢复某个线程的运行
5)`TIMED_WAITING`:超时等待状态,该状态不同于 WAITING,它是可以在指定的时间自行返回到 RUNNABLE 状态。
这个没啥好说的,就是各种带上了 timeout 的等待函数,额外要注意的就是 sleep 函数
6)`TERMINATED`:终止状态,表示当前线程已经执行完毕。
> 举一个线程状态转换的例子,帮助大家理解:
> - 首先,线程调用了 `Object.wait`,线程状态变为 WAITING
> - 当被另一个线程唤醒后,会先转换为 RUNNABLE 状态,等待操作系统分配 CPU 资源
> - 分配到 CPU 资源后,该线程去竞争锁,如果竞争成功,才可以继续往下运行;如果竞争失败,就会从 RUNNABLE 状态变为 BLOCKED 状态
>
> 
