[Java] Java线程生命周期总结
线程是操作里的一个概念,经常说:进程是操作系统资源分配的基本单位,线程是操作系统CPU资源分配的基本单位。Java以及其他程序设计语言,对操作系统的线程概念进行了封装,但是万变不离操作系统。Java程序里的线程的本质就是操作系统的线程。在操作系统的层面,线程有自己的生命周期,每个周期之间有自己的状态转换。
操作系统的线程生命周期
操作系统具有以下的五个生命周期:简称五状态模型

创建状态
- 创建进程时拥有PCB但其他资源尚未就绪的状态称为创建状态
- 操作系统提供fork函数接口创建线程
就绪状态
- 当进程被分配到除CPU以外所有必要的资源后
- 其他资源都准备好、只差CPU资源的状态为就绪状态
- 在一个系统中多个处于就绪状态的进程通常排成一个队列
执行状态
- 进程获得CPU,其程序正在执行称为执行状态
- 在单处理机中,在某个时刻只能有一个进程是处于执行状态
阻塞状态
- 进程因某种原因如:其他设备未就绪而无法继续执行
- 从而放弃CPU的状态称为阻塞状态
终止状态
- 进程结束由系统清理或者归还PCB的状态称为终止状态

Java线程的生命周期
Java具有六个线程生命周期

相比于操作系统,Java做了如下包装
- 将就绪状态和执行状态合并成RUNNABLE,这两个状态在操作系统调度层面有用,而 JVM 层面不关心这两个状态,因为 JVM 把线程调度交给操作系统处理了
- 细化了休眠状态,变成了BLOCKED、WAITTING、TIMED_WAITING
因此流程图也变为如下的:

RUNNABLE -> BLOCKED
线程等待 synchronized 的隐式锁。synchronized 修饰的方法、代码块同一时刻只允许一个线程执行,其他线程只能等待,这种情况下,等待的线程就会从 RUNNABLE 转换到 BLOCKED 状态。
线程调用阻塞式 API 时,是否会转换到 BLOCKED 状态呢?在操作系统层面,线程是会转换到休眠状态的,但是在 JVM 层面,Java 线程的状态不会发生变化,也就是说 Java 线程的状态会依然保持 RUNNABLE 状态。JVM 层面并不关心操作系统调度相关的状态,因为在 JVM 看来,等待 CPU 使用权(操作系统层面此时处于可执行状态)与等待 I/O(操作系统层面此时处于休眠状态)没有区别,都是在等待某个资源,所以都归入了 RUNNABLE 状态。
RUNNABLE -> WAITTING
RUNNABLE -> TIMED_WAITTING
- 调用带超时参数的 Thread.sleep(long millis) 方法;
- 获得 synchronized 隐式锁的线程,调用带超时参数的 Object.wait(long timeout) 方法;
- 调用带超时参数的 Thread.join(long millis) 方法;
- 调用带超时参数的 LockSupport.parkNanos(Object blocker, long deadline) 方法;
- 调用带超时参数的 LockSupport.parkUntil(long deadline) 方法。
TIMED_WAITTING相比较于WAITTING也就是多了一个超时的区别
NEW -> RUNNABLE
刚刚创建出来的线程就是NEW状态,而启动这个线程,就是调用线程的start()方法,此方法调用native方法start0(),也就是说:Java语言本身不能创建线程的
RUNNABLE -> TERMINATED
线程执行完 run() 方法后,会自动转换到 TERMINATED 状态,当然如果执行 run() 方法的时候异常抛出,也会导致线程终止。
GO线程相关
先埋个坑

浙公网安备 33010602011771号