[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

  • 获得 synchronized 隐式锁的线程,调用无参数的 Object.wait() 方法。
  • 调用无参数的 Thread.join() 方法。
  • 调用 LockSupport.park() 方法。

RUNNABLE -> TIMED_WAITTING

  1. 调用带超时参数的 Thread.sleep(long millis) 方法;
  2. 获得 synchronized 隐式锁的线程,调用带超时参数的 Object.wait(long timeout) 方法;
  3. 调用带超时参数的 Thread.join(long millis) 方法;
  4. 调用带超时参数的 LockSupport.parkNanos(Object blocker, long deadline) 方法;
  5. 调用带超时参数的 LockSupport.parkUntil(long deadline) 方法。

TIMED_WAITTING相比较于WAITTING也就是多了一个超时的区别

NEW -> RUNNABLE

刚刚创建出来的线程就是NEW状态,而启动这个线程,就是调用线程的start()方法,此方法调用native方法start0(),也就是说:Java语言本身不能创建线程的

RUNNABLE -> TERMINATED

线程执行完 run() 方法后,会自动转换到 TERMINATED 状态,当然如果执行 run() 方法的时候异常抛出,也会导致线程终止。

GO线程相关

先埋个坑

posted @ 2021-04-05 01:16  herrhu  阅读(146)  评论(0)    收藏  举报