Java线程状态切换图
  • 新建状态(NEW)

    状态说明:创建了线程对象,但没有调用其start方法

    此时,在操作系统层面,并没有创建真正的线程,所以不会获取到CPU执行时间

    发生场景:创建线程后,就处于该状态

  • 运行状态(RUNNABLE)

    状态说明:包括操作系统线程状态中的 Running 和 Ready

    发生场景:调用了 Thread.start() 方法

    此时,线程可能正在执行,也可能正在等待操作系统为之 分配执行时间

  • 限期等待状态(TIMED_WAITING

    状态说明:不会被分配处理器执行时间,无需等待被其他线程显示唤醒,超时过后会由系统自动唤醒

    发生场景:包括以下几种情况

    • 带有超时时间的 Thread.sleep 方法
    • 带有超时时间的 Object.wait 方法
    • 带有超时时间的 Thread.join 方法
    • 带有超时时间的LockSupport.parkNanos 方法
    • 带有超时时间的LockSupport.parkUntil 方法
  • 无限期等待状态(WAITING)

    状态说明:不会被分配处理器执行时间,需要等待被其他线程显示地唤醒

    发生场景:包括以下几种情况

    • 调用 Object.wait() 方法
    • 调用 Thread.join() 方法
    • 调用 LockSupport.park() 方法
  • 阻塞状态(BLOCKED)

    状态说明:阻塞等待,需要获取到一个排他锁,将在另一个线程放弃这个锁的时候发生

    发生场景:调用 synchronized 代码块 或 synchronized 方法(因为 synchronized 是互斥锁)

  • 终结状态(TERMINATED)

    状态说明:线程已经结束运行

    发生场景:包括以下几种情况

    • run() 方法正常执行完成

    • run() 方法抛出了异常

    • 手动调用 Thread.stop() 方法(被弃用) Thread.interrupt() 方法

      stop方法 与 interrupt 方法的区别

      • 因为stop方法 会 直接杀死线程,这种操作有风险

        因为如果线程持有了 ReentrantLock 锁,stop方法直接杀死了线程,导致线程没有释放锁,那么其他线程就没有机会获取到这把锁,从而一直等待下去

      • interrupt 方法 仅会通知线程,线程会有机会执行后续操作,线程也可以无视这个通知

        interrupt 的线程,收到通知的2种方式

        • 第一种方式:抛出异常
        1. 当前线程处于 WAITING TIMED_WAITING 时,如果其他线程调用了 该线程的 interrupt() 方法

          会使当前线程 返回到 RUNNABLE 状态,同时当前线程会抛出 InterruptedException

        2. 当前线程处于 RUNNABLE 状态 并且阻塞在 java.nio.channels.InterruptibleChannel 上时,如果其他线程调用了该线程的 interrupt 方法,当前线程会抛出 java.nio.channels.ClosedByInterruptException 异常

        3. 当前线程处于 RUNNABLE 状态 并且阻塞在 java.nio.channel.Selector 上时,如果其他线程调用该线程的 interrupt 方法,当前线程的java.nio.channel.Selector会立即返回

        • 第二种方式:主动检测

          如果线程处于 RUNNABLE 状态,并且没有阻塞在某个 I/O 操作下,如果其他线程调用了该线程的 interrupt 方法, 那么当前线程需要通过主动检测 isInterrupted() 方法 来检测自己是否被中断了。

简化后的生命周期

简化后的线程生命周期