【Java EE】深入理解 Java 线程的生命周期与状态转换

多线程编程在 Java 中是实现高效并发的核心技术之一。每个线程在其生命周期内会经历多个状态,这些状态反映了线程在特定时间点的行为与系统资源的使用情况。了解线程的状态及其转换机制,对于编写健壮的并发程序尤为重要。本文将深入探讨 Java 线程的六种状态、每种状态的含义、状态之间的转换条件以及线程状态在实际应用中的意义。

1. Java 线程的六种状态

根据 Java 虚拟机规范,线程状态可以被分为六种:

  1. 新建(New)
  2. 可运行(Runnable)
  3. 阻塞(Blocked)
  4. 等待(Waiting)
  5. 计时等待(Timed Waiting)
  6. 终止(Terminated)

这些状态为理解线程的生命周期提供了基本框架,帮助开发者掌握线程在不同场景下的行为。

2. 线程状态的含义详解

(1)新建(New)

线程处于新建状态时,它仅仅是一个被创建但尚未启动的对象。在这个状态下,线程对象已经被实例化,但线程还未被调度器纳入可运行线程的集合中。此时,线程还没有占用任何系统资源。

Thread thread = new Thread(() -> {System.out.println("线程处于新建状态");
});
// 线程尚未启动,处于新建状态

(2)可运行(Runnable)

可运行状态的线程表示它已经准备好执行代码,但并不一定立即执行。Java 中的可运行状态不仅包括真正占用 CPU 时间片的状态,也包括线程在操作系统层面处于等待资源调度的状态。线程在调用 start() 方法后,从新建状态转为可运行状态。

thread.start(); // 线程进入可运行状态

可运行状态的线程可以随时被操作系统调度执行,而调度的时机取决于系统的线程调度策略(例如时间片轮转、优先级调度等)。

(3)阻塞(Blocked)

阻塞状态是线程生命周期中的一个重要环节,通常发生在线程等待获取一个被其他线程持有的锁时。当线程试图进入同步代码块或者同步方法时,如果无法获得锁,它将进入阻塞状态。阻塞状态的线程无法继续执行,直到它成功获取锁为止。

public class Main {private static final Object lock = new Object();public static void main(String[] args) {Thread thread1 = new Thread(() -> {synchronized (lock) {System.out.println(Thread.currentThread().getName() + " 获得了锁");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});Thread thread2 = new Thread(() -> {synchronized (lock) {System.out.println(Thread.currentThread().getName() + " 获得了锁");}});thread1.start();thread2.start();}
}

在这个例子中,thread1 先获得锁并进入同步代码块,thread2 尝试获取相同的锁,但在 thread1 释放锁之前,thread2 会进入阻塞状态。

(4)等待(Waiting)

等待状态表示线程在等待某个条件的发生,只有当另一个线程显式地唤醒它时,线程才能从等待状态返回到可运行状态。典型的场景包括调用 Object.wait()Thread.join()LockSupport.park() 等方法。

public class Main {private static final Object lock = new Object();public static void main(String[] args) {Thread thread = new Thread(() -> {synchronized (lock) {try {System.out.println("线程进入等待状态");lock.wait(); // 线程进入等待状态System.out.println("线程恢复执行");} catch (InterruptedException e) {e.printStackTrace();}}});thread.start();try {Thread.sleep(1000);synchronized (lock) {lock.notify(); // 唤醒等待线程}} catch (InterruptedException e) {e.printStackTrace();}}
}

在此示例中,线程在 wait() 方法调用后进入等待状态,直到其他线程调用 notify() 方法将其唤醒。

(5)计时等待(Timed Waiting)

计时等待状态与等待状态类似,区别在于计时等待是有时间限制的。如果线程在指定的时间内没有被唤醒,它会自动从计时等待状态返回到可运行状态。计时等待通常用于控制线程的超时行为,比如通过 Thread.sleep()Object.wait(long timeout)Thread.join(long millis) 等方法来实现。

public class Main {public static void main(String[] args) {Thread thread = new Thread(() -> {try {System.out.println("线程进入计时等待状态");Thread.sleep(3000); // 线程进入计时等待状态System.out.println("线程恢复执行");} catch (InterruptedException e) {e.printStackTrace();}});thread.start();}
}

在这个示例中,线程通过 Thread.sleep(3000) 进入计时等待状态,3秒后线程会自动恢复执行。

(6)终止(Terminated)

当线程的 run() 方法执行完成或由于未捕获的异常导致线程退出时,线程将进入终止状态。处于终止状态的线程不再具备可运行性,也不能被重新启动。在这种状态下,线程已经完成了其生命周期的所有阶段。

public class Main {public static void main(String[] args) {Thread thread = new Thread(() -> {System.out.println("线程运行完成");});thread.start();try {thread.join(); // 等待线程终止System.out.println("线程状态: " + thread.getState()); // 输出:TERMINATED} catch (InterruptedException e) {e.printStackTrace();}}
}

在该示例中,thread.join() 方法等待线程终止,终止后的线程状态为 TERMINATED

3. 线程状态之间的转换条件

线程的状态在其生命周期内根据特定条件进行转换。了解这些转换条件有助于我们更好地掌控线程的行为,并在开发过程中避免常见的并发问题。

  • 新建 -> 可运行:调用 start() 方法时,线程从新建状态进入可运行状态。
  • 可运行 -> 阻塞:线程试图获取一个被其他线程持有的锁时,会从可运行状态进入阻塞状态。
  • 阻塞 -> 可运行:当线程成功获取锁时,它会从阻塞状态返回到可运行状态。
  • 可运行 -> 等待:线程通过调用 Object.wait()Thread.join()LockSupport.park() 等方法进入等待状态。
  • 等待 -> 可运行:线程在被另一个线程显式唤醒(通过 Object.notify()notifyAll() 方法)后,从等待状态返回到可运行状态。
  • 可运行 -> 计时等待:线程通过调用具有超时参数的方法(如 Thread.sleep(long millis)Object.wait(long timeout) 等)进入计时等待状态。
  • 计时等待 -> 可运行:计时等待超时后,线程会自动从计时等待状态返回到可运行状态。
  • 可运行 -> 终止:当 run() 方法执行完成或线程因异常退出时,线程进入终止状态。

以下是线程状态转换的示意图:

        +--------------------+|                    |v                    |新建 (New) --> 可运行 (Runnable) <---> 计时等待 (Timed Waiting)|     ||     |阻塞 (Blocked)  |     |v     |等待 (Waiting)||终止 (Terminated)
4. 线程状态的实际应用与考虑

在实际开发中,线程状态的管理直接影响程序的正确性和性能。例如:

  • 死锁与阻塞状态:当多个线程相互等待对方释放资源时,可能会导致死锁问题,线程永远处于阻塞状态。合理设计锁的获取与释放机制可以避免死锁。

  • 等待/通知机制:在生产者-消费者模型中,生产者线程和消费者线程通过等待/通知机制实现高效的同步与通信。确保通知机制的正确性对于避免线程“假唤醒”非常关键。

  • 超时机制:通过计时等待,开发者可以为线程操作设置合理的超时时间,防止线程在等待过程中无限期地被挂起。超时机制在网络通信、文件 I/O 等场景中尤为重要。

结论

Java 线程的六种状态及其相互转换为我们提供了理解线程生命周期的基础。这些状态反映了线程在不同运行阶段的行为,也为我们管理线程提供了参考。在实际开发中,通过合理管理线程的状态,避免常见的并发问题,可以显著提升程序的可靠性和性能。

掌握线程的状态与转换规律,将使我们能够编写出更加健壮的并发程序,为复杂的多线程环境下提供稳定可靠的解决方案。出高效且安全的多线程程序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/51375.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python 零星知识点

一、头部注释 在Python脚本中&#xff0c;头部注释&#xff08;也称为文档字符串或模块级注释&#xff09;用于提供关于脚本的元数据和描述信息。除了指定解释器和编码方式外&#xff0c;还可以包含其他信息。以下是一些常见的头部注释示例&#xff1a; 1.模块描述 "&qu…

【MySQL】MySQL表的增删改查(初阶)

欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 表内容操作 插入内容 按顺序插入 指定某些列插入 一次插入多行记录 插入时间 查询表内容 全列查询 指定列查询 指定表达式查询 用as取别名 ​编辑 去重查询 排序查询…

不同搜索引擎蜘蛛的功能、‌抓取策略与技术实现差异探究

搜索引擎作为互联网信息检索的重要工具&#xff0c;‌其核心功能依赖于背后的“蜘蛛”程序。‌这些蜘蛛程序负责访问互联网上的各种内容&#xff0c;‌并建立索引数据库&#xff0c;‌以便用户能够快速准确地找到所需信息。‌然而&#xff0c;‌不同搜索引擎的蜘蛛在功能、‌抓…

Axios介绍;前后端分离开发的介绍;YAPI的使用;Vue项目简介、入门;Elementui的使用;nginx介绍

1 Ajax 1.1 Ajax介绍 1.1.1 Ajax概述 我们前端页面中的数据&#xff0c;如下图所示的表格中的学生信息&#xff0c;应该来自于后台&#xff0c;那么我们的后台和前端是互不影响的2个程序&#xff0c;那么我们前端应该如何从后台获取数据呢&#xff1f;因为是2个程序&#xf…

仿Muduo库实现高并发服务器——EventLoop模块

我刚开始看这个模块时&#xff0c;也是看不明白&#xff0c;什么是事件管理模块。 此时此刻&#xff0c;大领导的背影&#xff0c;还是那么清晰。结合故事模块&#xff0c;慢慢理。 EventLoop模块 成员&#xff1a; 绿色&#xff1a; 利用智能指针对new出来的对象进行管理&…

武汉流星汇聚:亚马逊赋能中小企业,跨境电商市场举足轻重地位稳

在全球经济一体化的浪潮中&#xff0c;跨境电商作为推动国际贸易的重要力量&#xff0c;正以前所未有的速度发展。在这场全球性的商业竞赛中&#xff0c;亚马逊以其卓越的市场表现、强大的技术实力和深厚的品牌影响力&#xff0c;稳居跨境电商市场的领头羊地位&#xff0c;其举…

多任务下载工具.exe

关键代码 void DownloadTask::StartDownload(const QUrl url,QFile *file,qint64 startPoint/* 0 */,qint64 endPoint/* -1 */) {if( NULL file )return;m_HaveDoneBytes 0;m_StartPoint startPoint;m_EndPoint endPoint;m_File file;//根据HTTP协议&#xff0c;写入RANGE…

Vue3基础2

1.Hooks 就是进行数据的封装&#xff0c;同一种类型的 数据 方法 计算属性 &#xff0c;放在一起 命名规范 use功能名称.ts 或.js 创建一个文件夹 hooks 1.useDog.ts import { reactive,onMounted } from "vue"; import axios from "axios";export def…

[数据集][目标检测]红外场景下车辆和行人检测数据集VOC+YOLO格式19069张4类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;19069 标注数量(xml文件个数)&#xff1a;19069 标注数量(txt文件个数)&#xff1a;19069 标…

SQL AI 工具:颠覆数据库管理与分析的创新力量

一、SQL AI 工具的兴起与发展 在当今数字化的时代&#xff0c;数据量呈现爆炸式增长&#xff0c;企业和个人对于高效管理和分析数据的需求日益迫切。传统的数据库管理和查询方式&#xff0c;对于非技术人员来说存在较高的门槛&#xff0c;操作复杂且耗时。这一背景为 SQL AI 工…

人工智能开发NPU使用

1. NPU使用 RK3588 内置 NPU 模块, 处理性能最高可达6TOPS&#xff08;即每秒处理6万亿次操作&#xff09;。这款NPU不仅拥有强大的计算能力&#xff0c;支持TensorFlow、Caffe、Tflite、Pytorch、Onnx NN、Android NN 等常见框架。使用该NPU需要下载RKNN SDK&#xff0c;RKNN…

深度学习--自监督学习

自监督学习是一种无需大量人工标注的数据驱动方法&#xff0c;在生成模型中应用广泛。自监督学习通过利用数据中的固有结构或属性创建“伪标签”&#xff0c;使模型在没有人工标签的情况下进行学习。这种方法既提高了模型的训练效率&#xff0c;又降低了对标注数据的依赖。 概…

VMware安装Ubuntu20.04

1. 下载 整理的镜像链接 阿里网盘&#xff1a; 阿里云盘分享 提取码: l7y1 2. 新建虚拟机向导 选择自定义&#xff0c;然后下一步。 默认配置&#xff0c;下一步。 选择稍后安装操作系统&#xff0c;下一步。 选择操作系统Linux&#xff0c;版本Ubuntu64位&#xff0c;下一…

OCC笔记:Windows下OCC的编译

一、源码下载 进OCC官网下载https://dev.opencascade.org/release即可&#xff0c;或直接Clone它的Git库https://dev.opencascade.org/resources/git_repository&#xff0c;本文用的源码库版本为7.4.0&#xff08;我本机安装的VS2013&#xff0c;我又想用到AIS_ViewCube&…

AList嵌入动态验证码实现动态校验

前言 晓杰利用ALists创建了个网盘资源站&#xff0c;想着如何增加个动态验证码进行验证后才能进行访问下载&#xff0c;刚开始利用了固定的验证码&#xff0c;用户可以通过JS代码中进行绕过或直接拿到验证码&#xff0c;经过晓杰多次优化&#xff0c;最终版本支持动态获取验证…

Linux(面试篇)

目录 什么是Linux 什么是Linux内核&#xff1f; Linux的基本组件是什么&#xff1f; Bash和Dos之间基本区别是什么&#xff1f; 什么是Root账户 什么是Bash? 什么时CLI? Linux的目录结构时怎样的&#xff1f; 什么是硬链接和软链接&#xff1f; 什么叫CC攻击&#…

IP代理可以做爬虫吗?探讨其可行性与相应实践

IP代理在网络爬虫中的应用 在网络爬虫的世界里&#xff0c;IP代理就像是爬虫的“隐形斗篷”&#xff0c;帮助它们在获取数据的过程中隐藏真实身份&#xff0c;避免被目标网站识别和封禁。那么&#xff0c;IP代理到底能否用于爬虫呢&#xff1f;答案是肯定的&#xff01;接下来…

Ajax-04

一.同步代码和异步代码 同步代码&#xff1a;浏览器按照我们书写代码的顺序一行一行地执行程序的。在上一行完成后会执行下一行。 同步代码&#xff1a;逐行执行&#xff0c;需原地等待结果&#xff0c;才继续向下执行 异步代码&#xff1a;可以在执行一个可能长期运行的任务…

docker容器图形化管理之Portainer

docker容器轻量级图形页面管理之Portainer 1、查看portainer镜像 [rootlocalhost ~]# docker search portainer 2、下载portainer镜像 [rootlocalhost ~]# docker pull portainer/portainer #选择喜欢的portainer风格镜像下载 3、启动dockerui容器 [rootlocalhost ~]# doc…

昂科烧录器支持Melexis迈来芯的位置传感器MLX90365KDC

芯片烧录行业领导者-昂科技术近日发布最新的烧录软件更新及新增支持的芯片型号列表&#xff0c;其中Melexis迈来芯的位置传感器MLX90365KDC已经被昂科的通用烧录平台AP8000所支持。 MLX90365KDC是第II代Triaxis位置传感器IC。 这款单片器件可凭借其表面的集磁点(IMC)&#xf…