当前位置: 首页 > news >正文

Java线程状态及其流转

在Java编程中,线程是一种重要的并发实体。为了更好地理解和管理多线程应用程序,我们需要清楚线程的不同状态及其流转机制。本文将详细介绍Java中线程的几种主要状态以及它们之间的转换关系。

一、线程状态概述

Java线程的生命周期有多个状态,主要包括以下几种:

  1. 新建状态(New)
  2. 就绪状态(Runnable)
  3. 运行状态(Running)
  4. 阻塞状态(Blocked)
  5. 等待状态(Waiting)
  6. 超时等待状态(Timed Waiting)
  7. 终止状态(Terminated)

每一种状态代表着线程在其生命周期中的不同阶段,下面我们将逐一解析每个状态以及状态之间的流转。

二、各线程状态详解

1. 新建状态(New)

当创建一个线程对象时,该线程处于新建状态,此时线程尚未开始执行。只有当你调用 start() 方法时,新建状态的线程才能进入就绪状态。

示例代码

Thread thread = new Thread(() -> {System.out.println("线程正在执行...");
});

2. 就绪状态(Runnable)

新建状态的线程在调用 start() 方法后进入就绪状态。此时线程处于等待系统调度的状态,准备好随时启动执行。

示例代码

thread.start(); // 线程进入就绪状态

注意:就绪状态的线程不一定在运行,它只是等待线程调度器分配CPU时间。

3. 运行状态(Running)

当线程被分配到CPU时,线程进入运行状态。此时,线程正在执行它的任务。

  • 线程从就绪状态转换为运行状态是由线程调度器决定的。
  • 运行状态的线程可能会因为时间片用尽、调用 wait()sleep() 方法或由于其他线程抢占等原因而转移到其他状态。

4. 阻塞状态(Blocked)

阻塞状态的线程是因为尝试获取锁(synchronized)而被阻塞。当两个或多个线程需要相同的资源(例如一个对象的锁)时,只有获得锁的线程才能执行,而其他线程会被阻塞。

示例代码

synchronized (someObject) {// 执行的代码
}

如果另一个线程已经持有 someObject 的锁,则当前线程会进入阻塞状态,直到能够获取锁为止。

5. 等待状态(Waiting)

线程进入等待状态通常是由于调用了以下方法之一:

  • Object.wait()
  • Thread.join()
  • LockSupport.park()

在等待状态下的线程不会被线程调度器选中执行,直到其他线程调用 notify()notifyAll() 或者 join() 的线程结束。

示例代码

synchronized (someObject) {someObject.wait(); // 进入等待状态
}

6. 超时等待状态(Timed Waiting)

超时等待状态是一种特殊的等待状态,线程等待某个条件但设定了超时时间。线程会在等待时间结束后自动恢复到就绪状态。

例如,线程调用 Thread.sleep(millis)Object.wait(millis)

示例代码

Thread.sleep(1000); // 线程等待1秒

7. 终止状态(Terminated)

当线程的 run() 方法执行完毕,或者因为未处理异常而终止时,线程进入终止状态。此状态的线程无法再重新启动。

示例代码

public void run() {// 执行的代码
} // 线程执行到此,进入终止状态

线程一旦进入终止状态,它的生命周期就结束了。

三、线程状态流转

下面是一个详细的表格,内容包括线程状态、状态转换、触发条件以及实例代码说明。这个表格将帮助你更清晰地理解Java中线程的状态及其转换过程。

线程状态状态描述状态转换触发条件示例代码
新建(New)线程对象被创建,但尚未启动。调用 start() 方法调用 Thread t = new Thread()Thread t = new Thread();
就绪(Runnable)线程已启动,准备执行,但 CPU 未分配给它。由线程调度器分配 CPU 或调用 yield()调用 start() 后,等待 CPU 调度t.start();
运行(Running)线程正在执行任务。调度器分配 CPU 资源,或因时间片用尽被抢占CPU 调度// 代码在 run() 方法中执行
阻塞(Blocked)线程等待获取其他线程持有的锁。获取锁成功,或其他条件通知当前线程调用了 synchronized,但未获取锁synchronized(lock) { ... }
等待(Waiting)线程等待其他线程通知。由其他线程调用 notify()notifyAll()调用 wait()join()lock.wait();
超时等待(Timed Waiting)线程等待某个条件,但设定了超时时间。超时结束,或被调用 notify()调用 Thread.sleep(millis)wait(millis)Thread.sleep(1000);
终止(Terminated)线程生命周期结束。无法再转换,无论是正常结束还是异常run() 方法执行完毕或抛出未处理的异常public void run() { ... }

状态转换详细说明

  1. 新建(New)→ 就绪(Runnable)

    • 条件:调用 start() 方法,使线程准备执行。
    • 示例代码
      Thread thread = new Thread(() -> { /* 执行的任务 */ });thread.start();  // 线程从新建状态转到就绪状态
      
  2. 就绪(Runnable)→ 运行(Running)

    • 条件:线程调度器将 CPU 时间片分配给线程,使其进入运行状态。
    • 示例:后台执行的任务,调度器根据优先级选择线程。
  3. 运行(Running)→ 阻塞(Blocked)

    • 条件:线程尝试访问 synchronized 块或方法时,发现已被其他线程占用。
    • 示例代码
      synchronized(lock) {    // 访问被锁住的资源}
      
  4. 运行(Running)→ 等待(Waiting)

    • 条件:调用 wait()join()LockSupport.park(),进入等待状态。
    • 示例代码
      synchronized (lock) {    lock.wait(); // 进入等待状态,直到有其他线程调用notify}
      
  5. 运行(Running)→ 超时等待(Timed Waiting)

    • 条件:调用带有时间参数的方法,如 Thread.sleep(millis)wait(millis)
    • 示例代码
      Thread.sleep(1000); // 线程暂停1秒进入超时等待状态
      
  6. 阻塞(Blocked)→ 就绪(Runnable)

    • 条件:成功获取锁,线程重新进入就绪状态,等待 CPU 调度。
    • 示例:当锁被释放后,阻塞的线程尝试获取锁,成功时转为就绪状态。
  7. 等待(Waiting)→ 就绪(Runnable)

    • 条件:其他线程调用了 notify()notifyAll(),唤醒等待线程。
    • 示例代码
      // 在另一个线程synchronized (lock) {    lock.notify(); // 唤醒一个等待的线程}
      
  8. 超时等待(Timed Waiting)→ 就绪(Runnable)

    • 条件:等待超时到达,线程自动恢复就绪状态。
    • 示例:如上所示的 Thread.sleep 达到指定时间。
  9. 运行(Running)→ 终止(Terminated)

    • 条件:线程执行完毕,或者抛出未捕获的异常,线程自然结束。
    • 示例代码
      public void run() {    // 一些代码}  // 代码完成或抛出异常则终止
      

四、总结

了解Java线程的各个状态及其流转机制是掌握并发编程的基础。通过清晰的状态流转关系,可以帮助我们更有效地管理和调试多线程应用程序。希望本文能帮助到你在多线程编程中的学习与应用。

http://www.xdnf.cn/news/779329.html

相关文章:

  • 互联网大厂智能体平台体验笔记字节扣子罗盘、阿里云百炼、百度千帆 、腾讯元器、TI-ONE平台、云智能体开发平台
  • C++仿RabbitMQ实现消息队列
  • jwt token验证
  • 【Linux】线程互斥
  • Apache Druid
  • 安全-JAVA开发-第一天
  • AbMole| 3-Methyladenine (3-MA) (M2296;3-甲基腺嘌呤)
  • 仓颉项目调试配置与多文件场景下的问题解析
  • Kafka 和Redis 在系统架构中的位置
  • MySQL计算精度计算加减乘除取模方式和方法总计
  • MATLAB实战:视觉伺服控制实现方案
  • VS下C++及C#项目打包发布方法
  • 第1章_数据分析认知_知识点笔记
  • 连接关键点:使用 ES|QL 联接实现更丰富的可观测性洞察
  • qt控制台程序与qt窗口程序在读取数据库中文字段的差异!!巨坑
  • UniRig:如何在矩池云一站式解决 3D 模型绑定难题
  • 1.1Nodejs和浏览器中的二进制处理
  • 高密度电子设备的黄金搭档: 双面沉金PCB线路板
  • 简单实现Ajax基础应用
  • electron定时任务,打印内存占用情况
  • 【计算机网络】数据链路层——ARP协议
  • 系统架构设计论文
  • 星敏感器:卫星姿态测量的“星空导航仪”
  • Linux-GCC、makefile、GDB
  • 手动删除网页上的禁止复制事件
  • 平台化 LIMS 系统架构 跨行业协同与资源共享的实现路径
  • 从0开始学linux韦东山教程第四章问题小结(3)
  • vue-15 (实践练习:使用路由防护实现身份验证和授权)
  • 微软Build 2025:Copilot Studio升级,解锁多智能体协作未来
  • 05 APP 自动化- Appium 单点触控 多点触控