线程是如何在 6 种状态之间转换的?

news2024/11/18 14:03:10

Java全能学习+面试指南:https://javaxiaobear.cn

今天我们主要学习线程是如何在 6 种状态之间转换的。

线程的 6 种状态

就像生物从出生到长大、最终死亡的过程一样,线程也有自己的生命周期,在 Java 中线程的生命周期中一共有 6 种状态。

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

如果想要确定线程当前的状态,可以通过 getState() 方法,并且线程在任何时刻只可能处于 1 种状态。

New 新创建

下面我们逐个介绍线程的 6 种状态,如图所示,首先来看下左上角的 New 状态。

New 表示线程被创建但尚未启动的状态:当我们用 new Thread() 新建一个线程时,如果线程没有开始运行 start() 方法,所以也没有开始执行 run() 方法里面的代码,那么此时它的状态就是 New。而一旦线程调用了 start(),它的状态就会从 New 变成 Runnable,也就是状态转换图中中间的这个大方框里的内容。

Runnable 可运行

Java 中的 Runable 状态对应操作系统线程状态中的两种状态,分别是 Running 和 Ready,也就是说,Java 中处于 Runnable 状态的线程有可能正在执行,也有可能没有正在执行,正在等待被分配 CPU 资源。

所以,如果一个正在运行的线程是 Runnable 状态,当它运行到任务的一半时,执行该线程的 CPU 被调度去做其他事情,导致该线程暂时不运行,它的状态依然不变,还是 Runnable,因为它有可能随时被调度回来继续执行任务。

阻塞状态

接下来,我们来看下 Runnable 下面的三个方框,它们统称为阻塞状态,在 Java 中阻塞状态通常不仅仅是 Blocked,实际上它包括三种状态,分别是 Blocked(被阻塞)、Waiting(等待)、Timed Waiting(计时等待),这三 种状态统称为阻塞状态,下面我们来看看这三种状态具体是什么含义。

Blocked 被阻塞

首先来看最简单的 Blocked,从箭头的流转方向可以看出,从 Runnable 状态进入 Blocked 状态只有一种可能,就是进入 synchronized 保护的代码时没有抢到 monitor 锁,无论是进入 synchronized 代码块,还是 synchronized 方法,都是一样。

我们再往右看,当处于 Blocked 的线程抢到 monitor 锁,就会从 Blocked 状态回到Runnable 状态。

Waiting 等待

我们再看看 Waiting 状态,线程进入 Waiting 状态有三种可能性。

  1. 没有设置 Timeout 参数的 Object.wait() 方法。
  2. 没有设置 Timeout 参数的 Thread.join() 方法。
  3. LockSupport.park() 方法。

刚才强调过,Blocked 仅仅针对 synchronized monitor 锁,可是在 Java 中还有很多其他的锁,比如 ReentrantLock,如果线程在获取这种锁时没有抢到该锁就会进入 Waiting 状态,因为本质上它执行了 LockSupport.park() 方法,所以会进入 Waiting 状态。同样,Object.wait() 和 Thread.join() 也会让线程进入 Waiting 状态。

Blocked 与 Waiting 的区别是 Blocked 在等待其他线程释放 monitor 锁,而 Waiting 则是在等待某个条件,比如 join 的线程执行完毕,或者是 notify()/notifyAll() 。

Timed Waiting 限期等待

在 Waiting 上面是 Timed Waiting 状态,这两个状态是非常相似的,区别仅在于有没有时间限制,Timed Waiting 会等待超时,由系统自动唤醒,或者在超时前被唤醒信号唤醒。

以下情况会让线程进入 Timed Waiting 状态。

  1. 设置了时间参数的 Thread.sleep(long millis) 方法;
  2. 设置了时间参数的 Object.wait(long timeout) 方法;
  3. 设置了时间参数的 Thread.join(long millis) 方法;
  4. 设置了时间参数的 LockSupport.parkNanos(long nanos) 方法和 LockSupport.parkUntil(long deadline) 方法。

讲完如何进入这三种状态,我们再来看下如何从这三种状态流转到下一个状态。

想要从 Blocked 状态进入 Runnable 状态,要求线程获取 monitor 锁,而从 Waiting 状态流转到其他状态则比较特殊,因为首先 Waiting 是不限时的,也就是说无论过了多长时间它都不会主动恢复。

只有当执行了 LockSupport.unpark(),或者 join 的线程运行结束,或者被中断时才可以进入 Runnable 状态。

如果其他线程调用 notify() 或 notifyAll()来唤醒它,它会直接进入 Blocked 状态,这是为什么呢?因为唤醒 Waiting 线程的线程如果调用 notify() 或 notifyAll(),要求必须首先持有该 monitor 锁,所以处于 Waiting 状态的线程被唤醒时拿不到该锁,就会进入 Blocked 状态,直到执行了 notify()/notifyAll() 的唤醒它的线程执行完毕并释放 monitor 锁,才可能轮到它去抢夺这把锁,如果它能抢到,就会从 Blocked 状态回到 Runnable 状态。

同样在 Timed Waiting 中执行 notify() 和 notifyAll() 也是一样的道理,它们会先进入 Blocked 状态,然后抢夺锁成功后,再回到 Runnable 状态。

当然对于 Timed Waiting 而言,如果它的超时时间到了且能直接获取到锁/join的线程运行结束/被中断/调用了LockSupport.unpark(),会直接恢复到 Runnable 状态,而无需经历 Blocked 状态。

Terminated 终止

再来看看最后一种状态,Terminated 终止状态,要想进入这个状态有两种可能。

  • run() 方法执行完毕,线程正常退出。
  • 出现一个没有捕获的异常,终止了 run() 方法,最终导致意外终止。

注意点

最后我们再看线程转换的两个注意点。

  1. 线程的状态是需要按照箭头方向来走的,比如线程从 New 状态是不可以直接进入 Blocked 状态的,它需要先经历 Runnable 状态。
  2. 线程生命周期不可逆:一旦进入 Runnable 状态就不能回到 New 状态;一旦被终止就不可能再有任何状态的变化。所以一个线程只能有一次 New 和 Terminated 状态,只有处于中间状态才可以相互转换。

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

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

相关文章

揭开 Amazon Bedrock 的神秘面纱 | 基础篇

在 2023 年 4 月,亚马逊云科技曾宣布将 Amazon Bedrock 纳入使用生成式人工智能进行构建的新工具集。Amazon Bedrock 是一项完全托管的服务,提供各种来自领先 AI 公司(包括 AI21 Labs、Anthropic、Cohere、Stability AI 和 Amazon 等&#xf…

Python学习第一天-安装Python

文章目录 前言一、下载Python二、执行安装程序三、命令行验证总结 前言 以下榜单来自于TIOBE编程语言流行指数 不多说了,Python天下第一 一、下载Python 从官网下载Python安装程序 二、执行安装程序 找到python-3.12.0-amd64.exe执行,选择Install …

基于Python3的Scapy构造DNS报文

一:DNS协议 DNS(Domain Name System)协议是计算机网络中的一种基础协议,它用于将域名(如www.baidu.com)转换为IP地址(如192.168.0.1),从而实现计算机之间的通信。 DNS 分…

【Unity地编细节】为什么Unity笔刷在地形上面刷不出来

👨‍💻个人主页:元宇宙-秩沅 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 秩沅 原创 😶‍🌫️收录于专栏:unity细节和bug 😶‍🌫️优质专栏 ⭐【…

【编解码】解码字符串中的 UNICODE 字符

前言 由于前后端交互中编码的问题,出现了这样的一串字符: {"share_names":["\u4e2d\u6587\u8def\u5f84"]}出现了unicode编码作为字符串内容的情况,直接用json解析的话会报错,所以在json解析前需要先进行转码…

Linux | 深入浅出冯诺依曼

前言 但凡是科班出生的小伙伴多多稍稍应该都听过冯诺依曼体系吧,这似乎已成为入门计算机的必备知识了,本章就带着大家一起去理解冯诺依曼体系; 一、体系构成 冯诺依曼体系主张计算机由五大部件组成,如下所示; 输入设备…

进程(0)——计算机的中的软硬件【Linux】

进程(0)——计算机的中的软硬件【Linux】 一.硬件:1.1 冯诺依曼结构:1.2 存储金字塔1.2.1输入设备和存储器:1.2.2输出设备和存储器: 二.软件:2.1 操作系统2.1.1 如何理解管理: 博主自…

【Asp.net】Asp.net core中IIS配置注意事项

1、应用地址池设为无托管代码 一、提示:关于IIS上运行ASP.NET Core 站点的“HTTP 500.19”错误 安装dotnet-hosting-3.1.2-win.exe ASP.NET Core 3.1 Runtime (v3.1.2)下载地址: https://download.visualstudio.microsoft.com/download/pr/dd119832-dc4…

visual studio Qt 开发环境中手动添加 Q_OBJECT 导致编译时出错的问题

问题简述 创建项目的时候,已经添加了类文件,前期认为不需要信号槽,就没有添加宏Q_OBJECT,后面项目需要,又加入了宏Q_OBJECT,但是发现只是添加了一个宏Q_OBJECT,除此之外没有改动其它的代码,原本…

AWS Lambda 操作 RDS 示例

实现目标 创建一个 Lambda 接收调用时传入的数据, 写入 RDS 数据库 Post 表存储文章信息. 表结构如下: idtitlecontentcreate_date1我是标题我是正文内容2023-10-21 15:20:00 AWS 资源准备 RDS 控制台创建 MySQL 实例, 不允许 Public access (后面 Lambda 需要通过 VPC 访问…

【Qt进阶之自定义控件】使用QListWidget实现自定义Item效果

目的 Q:如何在Qt库的基础上,实现自定义控件呢? A:根据官方文档回答,就是继承需实现的控件,然后实现自定义功能。 以下是实现QListWidget控件的自定义item。 先看下最终效果是如何: listItem 主…

基于YOLO实现的口罩佩戴检测 - python opemcv 深度学习 计算机竞赛

文章目录 0 前言1 课题介绍2 算法原理2.1 算法简介2.2 网络架构 3 关键代码4 数据集4.1 安装4.2 打开4.3 选择yolo标注格式4.4 打标签4.5 保存 5 训练6 实现效果6.1 pyqt实现简单GUI6.3 视频识别效果6.4 摄像头实时识别 7 最后 0 前言 🔥 优质竞赛项目系列&#xf…

正则表达式,日期选择器时间限制,报错原因

目录 一、正则表达式 1、表达式含义 2、书写表达式 二、时间限制 1、原始日期选择器改造 2、禁止选择未来时间 3、从...到...两个日期选择器的时间限制 三、Uncaught (in promise) Error报错 一、正则表达式 1、表达式含义 (1)/^([a-zA-Z0-9_.…

2.1.1BFS中的Flood Fill和最短路模型

1.池塘计数 农夫约翰有一片 N ∗ M N∗M N∗M 的矩形土地。 最近,由于降雨的原因,部分土地被水淹没了。 现在用一个字符矩阵来表示他的土地。 每个单元格内,如果包含雨水,则用”W”表示,如果不含雨水,…

Unity 文字显示动画(2)

针对第一版的优化,自动适配文字大小,TextMeshPro可以拓展各种语言。第一版字母类语言效果更好。 using System.Collections; using System.Collections.Generic; using TMPro; using UnityEngine; using UnityEngine.UI;public partial class TextBeat…

CSS 三栏布局

左右两列定宽&#xff0c;中间自适应 浮动margin <style>.container {width: 500px;height: 200px;line-height: 200px;}.left {width: 100px;height: 100%;float: left;background: orange;text-align: center;}.right {width: 100px;height: 100%;float: right;back…

大模型必备算力:CPUGPU天梯图(2023年最新版)

在当今计算机世界&#xff0c;CPU、GPU和显卡的性能成为了衡量计算机性能的重要指标。今天深入了解CPU、GPU和显卡天梯图。 首先&#xff0c;CPU作为计算机的大脑&#xff0c;负责处理各种任务。它的性能主要由核心数、主频和缓存大小决定。其中&#xff0c;核心数和主频决定了…

学会使用Pandas进行数据清洗

大家好&#xff0c;如果你对数据科学感兴趣&#xff0c;那么数据清洗可能对你来说是一个熟悉的术语&#xff0c;本文将向你介绍使用Pandas进行数据清洗的过程。我们的数据通常来自多个资源&#xff0c;而且并不干净&#xff0c;它可能包含缺失值、重复值、错误或不需要的格式等…

二分查找,求方程多解

1.暴力遍历&#xff1a; 解为两位小数&#xff0c;故0.001的范围肯定可以包含&#xff08;零点存在&#xff09; 2.均分为区间长度为1的小区间&#xff08;由于两解&#xff0c;距离不小于1&#xff09;&#xff0c;一个区间最多一个解 1.防止两边端点都为解 2&…

JOSEF约瑟 JY82-III JY82-1P JY82J电压等级380V 检漏继电器 面板安装

系列型号&#xff1a; JY82A检漏继电器 JY82B检漏继电器 JY82-380/660检漏继电器 JY82-IV检漏继电器 JY82-2P检漏继电器 JY82-2/3检漏继电器 JJKY检漏继电器 JD型检漏继电器 JY82-IV;JY82J JY82-II;JY82-III JY82-1P;JY82-2PA;JY82-2PB 一、产品概述 检漏继电器 J…