JAVA之线程生命周期(状态)

Java线程状态:

Java线程在其生命周期中会经历一系列的状态变化,这些状态反映了线程在不同阶段的行为和能力。根据Java官方文档和JDK源码中java.lang.Thread.State枚举的定义,Java线程主要有 NEW(新建)、RUNNABLE(可运行/运行中)、BLOCKED(阻塞)、WAITING(等待)、 TIMED_WAITING(超时等待)、 TERMINATED(终止)六个状态:

  1. NEW(新建)

    • 描述:当线程对象被创建但尚未调用其start()方法时,线程处于NEW状态。此时,线程对象已经存在,但尚未与操作系统内核线程关联,也没有开始执行。
    • 行为:线程尚未开始执行任何代码,未分配任何系统资源。
  2. RUNNABLE(可运行/运行中)

    • 描述:一旦调用了start()方法,线程进入RUNNABLE状态。此时,线程已被操作系统认可,具备了执行资格,可以被调度器分配CPU时间片执行。实际上,RUNNABLE状态包含了两种不同的子状态:
      • 就绪(Ready):线程已经准备好运行,等待CPU调度。线程在等待队列中,一旦获得CPU时间片,就立即转为运行状态。
      • 运行(Running):线程正在使用CPU执行任务。这是线程真正执行代码的状态。
    • 行为:线程可能在CPU上执行,也可能在就绪队列中等待执行机会。在操作系统层面,这两个子状态并不区分,统一视为RUNNABLE。
  3. BLOCKED(阻塞)

    • 描述:线程因等待进入一个同步块(如synchronized关键字修饰的代码块或方法)而暂时停止运行,当前线程必须等待其他线程释放锁才能继续执行。阻塞状态发生在线程试图获取一个由其他线程持有的锁时。
    • 行为:线程暂停执行,不占用CPU,直到获得所需的锁。
  4. WAITING(等待)

    • 描述:线程处于一种无限期等待其他线程采取行动的状态。这通常发生在调用以下方法之一时:
      • Object.wait()(不带超时参数)。
      • Thread.join()(不带超时参数)。
      • LockSupport.park()
    • 行为:线程不会消耗CPU资源,只有当其他线程显式唤醒(如通过notify()notifyAll()LockSupport.unpark())或满足特定条件时,才会重新变为可运行状态。
  5. TIMED_WAITING(超时等待)

    • 描述:类似于WAITING状态,但线程具有超时限制。当超时时间到达或收到唤醒信号时,线程将恢复到可运行状态。这种状态发生在调用以下方法之一时:
      • Object.wait(long timeout)
      • Thread.sleep(long millis)
      • Thread.join(long millis)
      • LockSupport.parkNanos(long nanos)
      • LockSupport.parkUntil(long deadline)
    • 行为:线程暂停执行,不占用CPU,直到超时时间结束或被其他线程唤醒。
  6. TERMINATED(终止)

    • 描述:线程已完成其任务或因异常退出了run()方法。线程已经结束其生命周期,不能再被启动或执行任何操作。

    • 行为:线程彻底结束,系统资源被回收。可以通过isAlive()方法判断线程是否处于TERMINATED状态。

      Java线程的生命周期是从创建(NEW) 开始,经过 启动(RUNNABLE)可能的阻塞(BLOCKED)等待(WAITING/TIMED_WAITING)状态,最终到达终止(TERMINATED) 状态。这些状态之间并非严格单向过渡,线程可能会在RUNNABLE、BLOCKED、WAITING/TIMED_WAITING之间多次切换,直到最终结束。理解线程状态有助于分析多线程程序的行为,调试并发问题,以及设计高效的并发控制策略。

下面是一个简单的Java线程生命周期示例代码:

       Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("线程启动");
                try {
                    // 睡眠500毫秒
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程结束");
            }
        });

        // 打印线程的初始状态
        System.out.println("新建线程状态: " + thread.getState());

        // 启动线程
        thread.start();
        // 打印运行后的状态,这里可能会看到不同的状态,取决于CPU的调度
        // 通常会看到状态为NEW, TIMED_WAITING, RUNNABLE, TERMINATED
        System.out.println("线程运行后状态: " + thread.getState());
        try {
            Thread.sleep(1000); // 等待线程执行结束
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("线程结束状态: " + thread.getState());

Java线程状态切换:

Java线程状态之间的切换是由特定的事件或操作触发的。以下是各状态之间切换的具体情况和触发因素:

NEW → RUNNABLE

  • 触发操作:调用线程对象的start()方法。
  • 切换过程start()方法内部会调用JVM的底层API,请求操作系统创建一个内核线程,并将Java线程对象与之关联。此时,线程进入就绪队列,等待操作系统调度器分配CPU时间片。一旦获得CPU,线程开始执行其run()方法,进入RUNNING子状态。

RUNNABLE → BLOCKED

  • 触发事件:线程试图获取一个由其他线程持有的锁(如synchronized关键字修饰的代码块或方法、ReentrantLock等)。
  • 切换过程:线程暂停执行,放弃CPU,进入操作系统内核等待队列,等待锁的持有者释放锁。一旦锁被释放,线程重新进入就绪队列,等待调度执行。

RUNNABLE → WAITING

  • 触发操作:线程主动调用Object.wait()(无超时参数)、Thread.join()(无超时参数)或LockSupport.park()方法。
  • 切换过程:线程自愿放弃CPU,进入无限期等待状态,等待其他线程通过notify()notifyAll()LockSupport.unpark()方法唤醒。在等待期间,线程不消耗CPU资源,也不会被调度器选中执行。

RUNNABLE → TIMED_WAITING

  • 触发操作:线程调用带有超时参数的方法,如Object.wait(long timeout)Thread.sleep(long millis)Thread.join(long millis)LockSupport.parkNanos(long nanos)LockSupport.parkUntil(long deadline)
  • 切换过程:线程进入定时等待状态,放弃CPU,等待指定时间结束或接收到唤醒信号。在等待期间同样不消耗CPU资源。超时时间结束后,线程自动转入就绪状态,等待调度执行;若在此之前被其他线程唤醒,也会提前回到就绪状态。

(BLOCKED/WAITING/TIMED_WAITING) → RUNNABLE

  • 触发事件
    • BLOCKED:持有线程释放了线程正在等待的锁。
    • WAITING:其他线程调用了与当前线程相关联的Object.notify()Object.notifyAll()LockSupport.unpark()方法。
    • TIMED_WAITING:等待时间结束(超时)或接收到唤醒信号。
  • 切换过程:线程从等待队列移除,重新进入就绪队列,等待调度器分配CPU时间片。一旦获得CPU,线程继续执行其run()方法。

RUNNABLE → TERMINATED

  • 触发事件:线程的run()方法正常结束或抛出了未被捕获的异常。

  • 切换过程:线程执行完毕,操作系统内核线程被销毁,Java线程对象的状态被设置为TERMINATED,且不可再被启动。此时,线程占用的系统资源被回收。

    Java线程状态的切换主要由线程自身的方法调用、其他线程的操作(如释放锁、发送通知)以及系统的调度决策等因素驱动。这些状态之间的转换反映了线程在执行过程中对资源的竞争、协作以及生命周期的不同阶段。理解这些状态转换有助于分析多线程程序的行为,排查并发问题,以及优化线程的使用。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

执子之意

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值