目录

1.线程的状态

1.1 NEW

1.2 RUNNABLE

1.3 BLOCKED

1.4 WAITING

1.5 TIMED_WAITING

1.6 TERMINATED

2.线程状态的相互转换


在上期的学习中,已经理解线程的启动(start())、休眠(sleep())、中断(interrupt())和等待(join())等核心概念。通过这些操作,线程会在不同的状态之间切换。那么,线程在这些过程中究竟经历了哪些状态?它们是如何转换的?这是本期要探讨的问题。

在前面谈到进程状态时,主要讲了就绪状态和阻塞状态,这是两个经典的状态。在线程中,线程的状态有六种,分别是:NEWRUNNABLEBLOCKEDWAITINGTIMED_WAITINGTERMINATED。这几个状态在 Java 中属于枚举类型,可以用代码实现查看这些状态:

public class Demo14 {public static void main(String[] args) {for (Thread.State state : Thread.State.values()) {System.out.println(state);}}
}

下面将对它们一 一介绍。

1.线程的状态

1.1 NEW

小帅对自己的女神小美仰慕已久,小帅同学打算好好打扮自己去追求女神小美,但是小帅心里胆怯,所以到目前为止,只是停留在仰慕的状态。此时小帅心里有追求女神小美的想法,但还没开始行动 start(),属于 NEW 状态。

NEW:是指一个线程已经被创建(new),但是还没开始执行的状态,称新建状态,也就是这个时候还没用调用 start()

public class Demo14 {public static void main(String[] args) {Thread thread = new Thread(() -> {//.........},"小帅");System.out.println(thread.getName() + ":" + thread.getState());//thread.start();//这里已经注释,没有调用start()}
}

运行结果:

1.2 RUNNABLE

终于,小帅下定决心,开启了对小美的追求之路。每天会和女神聊聊天,偶尔会约女神吃饭,也会给女神送礼物。此时小帅已经有实际行动了 start(),女神小美可能会立即回复,也有可能在忙其他事情,属于 RUNNABLE 状态。

RUNNABLE是指线程正在 JVM 中正在执行或者准备执行的状态,成可运行状态。也就是线程已经创建,并且调用了 start() 方法,新建线程开始执行。

public class Demo14 {public static void main(String[] args) {Thread thread = new Thread(() -> {},"小帅");System.out.println("调用start()前:" + thread.getName() + ":" + thread.getState());thread.start();System.out.println("调用start()后:" + thread.getName() + ":" + thread.getState());}
}

运行结果:

1.3 BLOCKED

小帅追求一段时间后,小美也对他有所回应,于是小帅想约小美周末一起看个电影,但是小美说你约晚了,周末要和好闺蜜一起去逛街。此时小帅不能约到小美,因为小美被闺蜜占用了,属于BLOCKED 状态。

BLOCKED:是指线程处于阻塞状态。这个是由于锁导致的,在下期线程安全问题会有讲解,这里先做一个了解。

public class Demo14 {public static void main(String[] args) throws InterruptedException {Object locker = new Object();Thread thread1 = new Thread(() -> {synchronized (locker){while (true) {System.out.println("闺蜜和小美在逛街....");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}},"闺蜜");Thread thread2 = new Thread(() -> {synchronized (locker){System.out.println("小帅约小美看电影....");}},"小帅");thread1.start();thread2.start();}
}

这里需要借助 jconsole 查看状态,关于 jconsole 在前面的文章《多线程——认识Thread类和创建线程》有讲。状态如下:

可以看到,“小帅”这个线程的状态就是 BLOCKED。

1.4 WAITING

时间来到第二周,虽然上周小帅没有约到小美一起看电影,但是啊,小帅没有放弃,于是小帅再次鼓气勇气再约女神一次,这次女神说这周末目前没有安排,但是这周工作有点忙,具体要看后面的时间安排,于是说“等我有时间联系你把”,但是小美并没有说会多久联系。于是呢,小帅觉得有点希望的,所以就一直等啊等,不分白天黑夜的一直在等女神的消息。此时,小帅一直等,没有期限的等待就属于 WAITING 状态。

WAITING是指某线程无限期等待其他线程执行特定任务的状态,称等待状态。也就是说需要其他线程完成一定的任务后,这个状态才能进行,需要调用 join() 方法。

public class Demo14 {public static void main(String[] args) throws InterruptedException {Thread thread1 = new Thread(() -> {while (true) {try {System.out.println("等待小美联系中....");Thread.currentThread().join();} catch (InterruptedException e) {throw new RuntimeException(e);}}},"小帅");Thread thread2 = new Thread(() -> {System.out.println("回复了小帅的邀约....");},"小美");thread1.start();thread1.join();thread2.start();}
}

借助 jconsole 查看状态,状态如下:

1.5 TIMED_WAITING

如果上面例子中,如果小美对小帅说“我这周比较忙,不一定有时间,我两三天内再回复你能不能出去看电影吧。”此时,小帅就会等小美的回复,但不会一直等下去了,最多就等三天,此时的等待就属于 TIMED_WAITING。

TIMED_WAITING是指线程在指定的时间内等待,这个等待有期限,称计时等待状态

public class Demo14 {public static void main(String[] args) throws InterruptedException {Object locker = new Object();Thread thread1 = new Thread(() -> {while (true) {System.out.println("等待小美联系中....");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}},"小帅");Thread thread2 = new Thread(() -> {System.out.println("回复了小帅的邀约....");},"小美");thread1.start();thread1.join(5000);//这里设置等待5秒thread2.start();}
}

借助 jconsole 查看状态,状态如下:

1.6 TERMINATED

小帅和小美在联系一段时间后,小帅和小美决定彼此并不合适,所以并没有在一起,小帅也放弃了追求小美,至此小帅对仰慕已久的女神的追求彻底结束了,属于 TERMINATED 状态。

TERMINATED是指线程执行完毕的状态,称终止状态。

public class Demo14 {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(()->{//....},"小帅");thread.start();thread.join();System.out.println(thread.getName() + "对女神的追求结束了... 现在的状态是:" + thread.getState());}
}

运行结果:

2.线程状态的相互转换

虽然线程状态的相互转换看似复杂,但主要是理解各个状态的含义以及是怎么发生的,这对于在后续的多线程学习中是非常重要的,尤其是调试程序找 bug 的时候,想要在多线程程序中进行调试,理解线程的状态是非常重要的,并且还需会使用 jconsole 或者其他根据查看当前线程的状态,比如前文使用 jconsole 查看状态时,还可以看到一些其他信息比如当前的状态是发生在哪一行。在这张转换图里,看到了一些方法比如 wait(),这个也是等待的方法,用法和 join() 类似,但在这里不深入讲解,在后面会专门写一期 wait() 的用法,以及 synchronized() { } 等都会详细解析介绍到。


本期主要介绍多线程的线程状态,主要过程状态是NEW -> RUNNABLE -> TERMINATED,然后在这个过程中发生一些状态转换,主要理解每个状态的含义并可以借助一些工具如  jconsole 查看线程状态。

从多线程的创建学习到现在,我们也理解了多线程的优势,但是那多线程一定很安全吗?是不是多线程可以随意使用呢?在 Java 基础学习中,我们谈到 StringBuffer 和 StringBuilder 时,说 StringBuffer 是线程安全的,而 StringBuilder 是线程不安全的。可见线程会存在安全问题,为什么会有线程安全问题以及导致线程安全问题的原因是什么?

欲知后事如何,且听下回分解!

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

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

相关文章

IMX6ULL的设备树文件简析

先分析一个完整的设备树,是怎么表达各种外设信息的。以imux6ull开发板为例进行说明。这个文件里就一个设备信息才这么点内容,是不是出问题了?当然不是,我们知道dts文件是可包含的,所以,最终形成的一个完整文…

【ARM】PACK包管理

1、 文档目标对 pack 包的管理有更多的了解。2、 问题场景客户在安装了过多的 pack 包导致软件打开比较慢,各种 pack 包颜色的区别,及图标不同。3、软硬件环境1)、软件版本:Keil MDK 5.392)、电脑环境:Wind…

【Kubernetes】知识点4

36. 说明K8s中Pod级别的Graceful Shutdown。答:Graceful Shutdown(优雅关闭)是指当 Pod 需要终止时,系统给予运行中的容器一定的时间来等待业务的应用的正常关闭(如保存数据、关闭连接、释放资源等)&#x…

Paraverse平行云实时云渲染助力第82届威尼斯电影节XR沉浸式体验

今年,Paraverse平行云实时云渲染平台LarkXR,为享有盛誉的第82届威尼斯国际电影节(8月27日至9月6日)带来沉浸式体验。 LarkXR助力我们的生态伙伴FRENCH TOUCH FACTORY,实现ITHACA容积视频的XR交互演示,从意大…

大数据开发计划表(实际版)

太好了!我将为你生成一份可打印的PDF版学习计划表,并附上项目模板与架构图示例,帮助你更直观地执行计划。 由于当前环境无法直接生成和发送文件,我将以文本格式为你完整呈现,你可以轻松复制到Word或Markdown中&#xf…

GitLab 18.3 正式发布,更新多项 DevOps、CI/CD 功能【二】

沿袭我们的月度发布传统,极狐GitLab 发布了 18.3 版本,该版本带来了通过直接转移进行迁移、CI/CD 作业令牌的细粒度权限控制、自定义管理员角色、Kubernetes 1.33 支持、通过 API 让流水线执行策略访问 CI/CD 配置等几十个重点功能的改进。下面是对部分重…

Docker学习笔记(二):镜像与容器管理

Docker 镜像 最小的镜像 hello-world 是 Docker 官方提供的一个镜像,通常用来验证 Docker 是否安装成功。 先通过 docker pull 从 Docker Hub 下载它。 [rootdocker ~]# docker pull hello-world Using default tag: latest latest: Pulling from library/hello-wor…

STM32F103C8T6开发板入门学习——寄存器和库函数介绍

学习目标:STM32F103C8T6开发板入门学习——寄存器和库函数介绍学习内容: 1. 寄存器介绍 1.1 存储器映射 存储器本身无固有地址,是具有特定功能的内存单元。它的地址是由芯片厂商或用户分配,给存储器分配地址的过程就叫做存储区映射…

【CouponHub项目开发】使用RocketMQ5.x实现延时修改优惠券状态,并通过使用模板方法模式重构消息队列发送功能

在上个章节中我实现了创建优惠券模板的功能,但是,优惠券总会有过期时间,我们怎么去解决到期自动修改优惠券状态这样一个功能呢?我们可以使用RocketMQ5.x新出的任意定时发送消息功能来解决。 初始方案:首先在创建优惠券…

Claude Code SDK 配置Gitlab MCP服务

一、MCP配置前期准备 (一)创建个人令牌/群组令牌 我这里是创建个人令牌,去到首页左上角,点击头像——>偏好设置——>访问令牌——>添加新令牌 (二)配置mcp信息 去到魔塔社区,点击mc…

Eclipse 常用搜索功能汇总

Eclipse 常用搜索功能汇总 Eclipse 提供了多种搜索功能,帮助开发者快速定位代码、文件、类、方法、API 等资源。以下是详细的使用方法和技巧。 一、常用搜索快捷键快捷键功能描述Ctrl H打开全局搜索对话框,支持文件、Java 代码、任务等多种搜索。Ctrl …

关于Spring的一些理解

Spring整体结构:Spring实际运行场景:基础 Spring启动过程 传统Spring: (1)初始化准备阶段 (2)容器创建与注入 (3)Bean工厂后置处理 (4)Bean工厂后…

Windows右下角系统托盘图标快速显示或隐藏

系统托盘指的是Windows电脑桌面右下角的区域,包括时间、wifi(网络)、音量、电源、输入法、一些程序/应用等。启动了应用后,Windows会把部分应用的图标显示或隐藏在系统托盘区。我们可以根据需要快速显示或隐藏相关应用&#xff0c…

Kotlin编程学习记录2

Kotlin编程学习记录2——条件与循环 条件语句:if 与 when ​ Kotlin 的控制流把“表达式优先”作为设计原则——if、when 不只是控制语句,都可以作为表达式使用并返回值,这影响了日常代码风格(更函数式、可组合)。笔…

印度物联网崛起:政策红利下的千亿蓝海与本土化博弈

印度物联网市场正处于快速发展阶段,2025年市场规模预计达到200亿美元,主要得益于政府"数字印度"计划和智能城市项目的推动。蜂窝物联网连接数在2024年同比增长34%,2025年Q1增速进一步提升至32%,其中智能电表部署和资产追踪应用成为核心驱动力。然而,市场也面临着…

html学习:

ok,今天准备学一下html&#xff0c;花费点时间整理一下&#xff1a; HTML标签的语法格式 HTML 中的标签就像关键字一样&#xff0c;每个标签都有自己的语义&#xff08;含义&#xff09;。 HTML 标签的语法格式 属性↓ <div class"begin">cyx</div>↑…

CRYPT32!PkiAsn1Decode函数分析的一个例子

第一部分&#xff1a; 0: kd> g Breakpoint 35 hit CRYPT32!PkiAsn1Decode: 001b:75c9af0c 55 push ebp 1: kd> kc# 00 CRYPT32!PkiAsn1Decode 01 CRYPT32!PkiAsn1DecodeAndAllocInfo 02 CRYPT32!PkiAsn1DecodeAndAllocInfoEx 03 CRYPT32!Asn1InfoDecode…

大模型蒸馏、大模型微调、RAG

前言&#xff1a; 有很多同学想学习大模型开发&#xff0c;又无从下手&#xff0c;网上一搜&#xff0c;铺天盖地的付费课程。又不想当韭菜&#xff0c;打破认知障碍&#xff0c;通过自学&#xff0c;改变自己&#xff0c;改变世界&#xff01; 一、大模型蒸馏、微调、RAG的适…

25高教社杯数模国赛【E题保姆级思路+问题分析】

注&#xff1a;本内容由”数模加油站“ 原创出品&#xff0c;虽无偿分享&#xff0c;但创作不易。 欢迎参考teach&#xff0c;但请勿抄袭、盗卖或商用。 E 题 AI辅助智能体测 《国家学生体质健康标准》的颁布&#xff0c;有效地促进了大中小学生关注自身体质健康的发展&#xf…

基于单片机车内换气温度检测空气质量检测系统Proteus仿真(含全部资料)

全套资料包含&#xff1a;Proteus仿真源文件keil C语言源程序AD原理图流程图元器件清单说明书等 资料下载&#xff1a; 通过网盘分享的文件&#xff1a;资料分享 链接: 百度网盘 请输入提取码 提取码: tgnu 目录 资料下载&#xff1a; Proteus仿真功能 项目文件资料&#…