Java线程状态

前言

Java Thread类中定义了线程的整个生命周期的不同状态,一个线程在任意特定时刻只有一个状态,这些状态只是虚拟机中的状态并不能反映操作系统实际线程的状态。

线程状态

java.lang.Thread.State中共定义了6中状态:

  • NEW:线程只是完成初始化 还没启动
  • RUNNABLE:线程已经准备就绪,在java虚拟机中表示线程正在执行,但在操作系统层面 线程可能还在等待比如分配CPU或IO等资源。
  • BLOCKED: 此状态表示线程阻塞等待一个monitor lock进入一个synchronized限定的代码块或方法,或者 线程先进入synchronized限定的方法或代码块,但是调用了wait()方法并释放了获得的锁,
    等到再次被notify()唤醒 再次阻塞等待进入synchronized限定的代码块或方法中。即:A、B两个线程都需要获取锁来执行方法,A获得锁还未释放,那么B就处于BLOCKED状态
  • WAITING: 线程调用以下方法进入此状态:
    1. Object.wait() 无超时参数
    2. Thread.join() 无超时参数
    3. LockSupport.park()

线程进入此状态,等待另一个线程调用特定方法。例如:一个线程调用Object.wait()等待另一个线程调用Object.notify()Object.notifyAll();一个线程调用了Thread.join()则等待这个线程执行完毕进入
Terminated状态

  • TIMED_WAITING: 线程调用以下指定等待时间等待线程的方法进入此状态:

    1. Thread.sleep()
    2. Object.wait() 带超时参数
    3. Thread.join() 带超时参数
    4. LockSupport.parkNanos()
    5. LockSupport.parkUntil()
  • TERMINATED: 线程已完成执行进入此状态

小结

我们日常工作当中经常会使用jstack命令来分析java的堆栈信息,比如

  • 当我们发现线程长时间处于BLOCKED状态,我们就需要分析下 是不是哪个地方锁没有释放?
  • 如果线程处于WAITING状态,需要分析下是不是调用Object.wait() LockSupport.park()的地方没有调用notify() LockSupport.unpark() 又或是调用时机不当

学习和深入理解线程状态 对于工作中快速、精准定位问题 jstack是武功招式 线程状态可谓是内功心法。。。

附张截取网络上的线程状态转移图:

函数名 JDK版本 消耗CPU 能否被Interrupt 核心方法 线程状态 备注
Spin Lock 1.0 native RUNNABLE
wait() 1.0 native WAITING
LockSupport.park() 1.5 native WAITING
sleep() 1.0 native TIMED_WAITING
join() 1.0 wait() WAITING
suspend() 1.0 native WAITING Deprecated
ReentrantLock.lock() 1.5 部分是 park() WAITING 有可interrupt版本lockInterruptibly()
Condition.await() 1.5 park() WAITING 有不可interrupt版本 awaitUninterruptibly()
FutureTask.get() 1.5 park() WAITING
坚持原创技术分享,您的支持将鼓励我继续创作!