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

【JavaEE】线程状态

目录

前言

一.线程状态图

二.线程状态

1.初始状态(NEW)

 2.运行状态(RUNNING)

 3.等待状态(WAITING)

4.超时等待(TIMED_WAITING)

5.阻塞状态(BLOCKED)

 6.终止状态(TERMINATED)

 三.线程状态间的转换

四.总结 


前言

线程状态及其状态转换是线程生命周期中的关键部分,下面我们就来讲解六种线程状态以及其如何转换。

一.线程状态图

线程状态其实是一种枚举类型Thread.State

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

 

  • NEW(初始):创建了一个线程,但还没有通过start方法调用。可以理解为安排了工作,但还没有开始工作。
  • RUNNABLE(运行):又分为Ready(就绪状态)Running(运行中状态)

当线程对象被创建之后,若有线程(比如main线程)调用了该线程对象的start,那么该线程就会进入可运行线程池进行等待线程调用,获取CPU的使用权,此时就处于Ready(就绪状态),当获取到cpu使用权之后,就转变为Running(运行中状态)。

Ready可以理解为即将开始工作,而Running即正在工作中。

  • BLOCKED(阻塞):线程试图获取一个锁对象,但此时锁对象被其他线程所占有,那么线程就进入阻塞等待,当获取到锁,则进入Running状态。
  • WAITING(等待):线程处于等待状态,等待其他线程唤醒,可以通过notify或者notifyAll方法来唤醒。
  • TIMED_WAITING(超时等待):可以在指定的时间内返回。可以使用带参数的sleep或者wait。
  • TERMINATED(终止):线程执行结束。主线程和子线程互不影响,子线程并不会因为主线程结束就结束。

二.线程状态

1.初始状态(NEW)

new关键字新建一个线程对象,这个线程就处于new状态

public static void main(String[] args) {// 创建一个线程,该线程在执行时会暂停1000毫秒Thread t=new Thread(()->{try {Thread.sleep(1000); // 模拟线程执行的延迟} catch (InterruptedException e) {e.printStackTrace(); // 处理线程被中断的异常}});System.out.println("t的线程状态:"+t.getState()); // 输出线程的当前状态}
t的线程状态:NEW

 2.运行状态(RUNNING)

分为RUNNING(运行状态)Ready(就绪状态).

  public static void main(String[] args) {Thread t=new Thread(()->{try {Thread.sleep(1000);}catch (InterruptedException e){e.printStackTrace();}});t.start();System.out.println("t的线程状态:"+t.getState()); // 输出线程的当前状态}
t的线程状态:RUNNABLE

 3.等待状态(WAITING)

等待状态下,没有时间限制,等被notify或者notifyAll唤醒

 public static void main(String[] args) throws InterruptedException {// 获取当前线程对象,用于后续检查线程状态Thread mainT=Thread.currentThread();// 使用lambda表达式创建一个新的线程,该线程用于展示线程的运行和状态检查Thread t=new Thread(()->{try {// 使新线程睡眠1秒,模拟耗时操作Thread.sleep(1000);}catch (InterruptedException e){// 如果线程在睡眠时被中断,打印异常信息e.printStackTrace();}// 输出线程的当前状态System.out.println("main线程状态:"+mainT.getState());});// 启动新线程,使其开始执行t.start();// 主线程等待新线程完成t.join();}
main线程状态:WAITING

4.超时等待(TIMED_WAITING)

TIMED_WAITING线程在等待唤醒,但设置了时限,当到达时限,会自动唤醒线程。

 public static void main(String[] args) throws InterruptedException {// 创建一个线程,该线程执行一个lambda表达式,使线程睡眠1秒Thread t = new Thread(() -> {try {Thread.sleep(1000); // 线程睡眠1000毫秒} catch (InterruptedException e) {e.printStackTrace(); // 捕获InterruptedException异常并打印堆栈跟踪}});t.start();//让main线程休眠Thread.sleep(50);System.out.println(t.getState());}
TIMED_WAITING

5.阻塞状态(BLOCKED)

 当进入到synchronized关键字修饰的方法或者代码块时,线程处于阻塞状态。

示例:两个线程争同一个锁对象,此时会引起锁竞争,没有获取到锁的线程,会进入阻塞状态,等待拿到锁的线程将锁释放。

   public static void main(String[] args) {final Object o=new Object();Thread t=new Thread(()->{synchronized (o) {while (true) {try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}});Thread tt=new Thread(()->{synchronized (o) {while (true) {try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}});t.start();tt.start();System.out.println("t的线程状态:"+t.getState()); // 输出线程的当前状态System.out.println("tt的线程状态:"+tt.getState()); // 输出线程的当前状态}
t的线程状态:RUNNABLE
tt的线程状态:BLOCKED

 6.终止状态(TERMINATED)

当线程执行结束,就处于终止状态。

需要注意:主线程和子线程互不影响,子线程并不会因为主线程结束就结束

/*** 程序入口* @param args 命令行参数* @throws InterruptedException 如果线程被中断*/public static void main(String[] args) throws InterruptedException {// 创建一个线程,该线程将休眠1秒Thread t = new Thread(() -> {try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}});// 启动线程t.start();// 等待线程结束t.join();// 输出线程的状态System.out.println(t.getState());}
TERMINATED

 三.线程状态间的转换

1.创建一个线程处于new,让其转换为running状态。可以看到线程t的状态为

NEW->RUNNING->TERMINATED

 public static void main(String[] args) throws InterruptedException {Thread t=new Thread(()->{try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}});System.out.println("t线程的状态"+t.getState());t.start();System.out.println("t线程的状态"+t.getState());t.join();System.out.println("t线程的状态"+t.getState());}
t线程的状态NEW
t线程的状态RUNNABLE
t线程的状态TERMINATED

2.将处于running的线程转换为wait 。(调用wait或者join都可)

 这里以join为例。

 public static void main(String[] args) throws InterruptedException {Thread main = Thread.currentThread();Thread t = new Thread(() -> {try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("main线程状态:"+main.getState());});t.start();System.out.println("main线程状态:"+main.getState());t.join();}
main线程状态:RUNNABLE
main线程状态:WAITING

wait方法:一般在synchronized修饰的代码块或者方法中使用。

调用wait会发生两件事:

(1)线程解锁“锁对象” (2)被解锁的线程会进入waiting状态。 

在使用wait方法时,需要先对线程加锁,否则会报错。因为wait会先解锁再进入等待状态

示例:

 public static void main(String[] args) throws InterruptedException {final Object locker = new Object();Thread t1=new Thread(()->{synchronized (locker){try {locker.wait();} catch (InterruptedException e) {throw new RuntimeException(e);}}},"t1");t1.start();System.out.println("t线程的状态"+t1.getState());Thread.sleep(50);System.out.println("t线程的状态"+t1.getState());}
t线程的状态RUNNABLE
t线程的状态WAITING

 但如果我们使用wait带参数的方法,那么状态还会是WAITING吗?

  public static void main(String[] args) throws InterruptedException {final Object locker = new Object();Thread t1=new Thread(()->{synchronized (locker){try {locker.wait(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}},"t1");t1.start();System.out.println("t线程的状态"+t1.getState());Thread.sleep(50);System.out.println("t线程的状态"+t1.getState());}
t线程的状态RUNNABLE
t线程的状态TIMED_WAITING

可以看到,当我们使用带参数的wait方法时,此时t的状态转变为TIMED_WAITING

3.若多个线程尝试获取同一个锁,那么就会引起对锁的竞争,即"锁竞争”。没用获取到线程的锁将会进入阻塞状态(BLOCKED),等线程获取到锁,才能执行。

示例:

    /*** 主函数,演示线程间的状态变化* @param args 命令行参数* @throws InterruptedException 当线程被中断时抛出此异常*/public static void main(String[] args) throws InterruptedException {// 创建一个对象作为锁final Object locker = new Object();// 创建线程t1,使用锁对象进行同步操作Thread t1=new Thread(()->{// 使用锁进行同步控制,形成死循环synchronized (locker){while(true){;}}},"t1");// 启动线程t1t1.start();// 输出线程t1的当前状态System.out.println("t1线程的状态"+t1.getState());// 创建线程t2,也使用锁对象进行同步操作Thread t2=new Thread(()->{// 使用锁进行同步控制,但没有进行循环,所以很快释放锁synchronized (locker){;}},"t2");// 启动线程t2t2.start();// 输出线程t2的当前状态System.out.println("t2线程的状态"+t2.getState());// 主线程等待50毫秒,以观察线程t2的状态变化Thread.sleep(50);// 再次输出线程t2的当前状态,以观察其变化System.out.println("t2线程的状态"+t2.getState());}
t1线程的状态RUNNABLE
t2线程的状态RUNNABLE
t2线程的状态BLOCKED

我们可以打开jconsole进行查看。

四.总结 

 

当我们创建一个线程对象时,此时线程就处于NEW状态。

调用start方法,会让线程进行运行状态,其中又分为RUNNING(运行中状态)和Ready(就绪状态)。

若想要让RUNNABLE中的线程进入WAITING(等待状态),可以使用wait或者join方法。想唤醒WAITING中的线程,需要使用notify或者nofityAll方法来唤醒。

可以使用带参数的join、sleep和wait方法,让RUNNABLE中的线程进入限时等待(TIMED_WAITING),当达到时时限,会自动唤醒线程。

 RUNNABLE中的线程若想出发BLOCKED状态,需要触发锁竞争

当线程中线程体的内容都执行完之后,就会进入TERMINATED(终止状态)


线程状态的讲解就先到这里了~

若有不足,欢迎指正~

相关文章:

【JavaEE】线程状态

目录 前言 一.线程状态图 二.线程状态 1.初始状态(NEW) 2.运行状态(RUNNING) 3.等待状态(WAITING) 4.超时等待(TIMED_WAITING) 5.阻塞状态(BLOCKED) 6.终止状态(TERMINATED) 三.线程状态间的转换 四.总结 前言 线程状态及其状态转换…...

C++笔记之编译过程和面向对象

回顾: “abcd”//数据类型 字符串常量 const char *p"abc"; new STU const char *//8 指针的内存空间 int float 指针的内存空间 p 指针指向的内存空间 "abc" 取决于字符串长度 指针变量的内容一级指针 指针变量的地址二级指针 …...

ModuleNotFoundError: No module named ‘tqdm‘

报错信息: tqdm是一个快速、可扩展的Python进度条库,用于展示迭代器的长循环执行进度。 解决:通过以下命令安装 使用conda命令安装 conda install tqdm使用pip安装: pip install tqdm...

东京电影节公布2024年竞赛片评审团成员并对其业绩分别进行评介 没什么含金量

第37届东京国际电影节竞赛单元评审团名单正式公布。 周五,电影节组织者宣布,香港电影制片人杜琪峰、匈牙利电影制片人伊尔迪科恩耶迪、日本女演员桥本爱和法国女演员基娅拉马斯楚安尼将与之前宣布的评审团主席梁朝伟一起担任 2024 年主竞赛评审团成员。 …...

智能景区垃圾识别系统:基于YOLO的深度学习实现

基于深度学习的景区垃圾识别系统(UI界面YOLOv8/v7/v6/v5代码训练数据集) 1. 引言 景区垃圾识别是环保管理的重要任务之一。传统的人工清理方式效率低、成本高,而借助深度学习技术可以实现自动化的垃圾检测与识别,提高景区的清洁…...

ventoy和微pe可以共存吗?ventoy和pe共存使用教程

Ventoy新一代多系统启动U盘解决方案。国产开源U盘启动制作工具,支持Legacy BIOS和UEFI模式,理论上几乎支持任何ISO镜像文件,支持加载多个不同类型的ISO文件启动,无需反复地格式化U盘,插入U盘安装写入就能制作成可引导的…...

如何获取和安装SSL证书

SSL(Secure Sockets Layer)证书是用于加密网站服务器和客户端之间通信的一种数字证书。它通过HTTPS协议保护数据传输的安全性,防止数据被窃听或篡改。本文将指导您如何为您的网站获取并安装SSL证书。 步骤1:选择SSL证书提供商 首…...

makefile在IC设计中的使用笔记

1 makefile在IC设计中的地位 关于makefile的详细介绍可以参考第一个连接,里面的内容很多也很详细。但在数字IC设计中,并不会把所有的用法都用到,下面记录一下主要用到的规则。 2 IC设计涉及到的主要用法 2.1 变量的定义和使用 在makefile…...

Suno声称在受版权保护的音乐上训练模型属于“合理使用“

继美国唱片业协会(RIAA) 最近对音乐生成初创公司 Udio 和 Suno 提起诉讼之后,Suno 在周四提交的一份法庭文件中承认,该公司确实使用了受版权保护的歌曲来训练其人工智能模型。但它声称,根据合理使用原则,这…...

Java | Leetcode Java题解之第316题去除重复字母

题目&#xff1a; 题解&#xff1a; class Solution {public String removeDuplicateLetters(String s) {boolean[] vis new boolean[26];int[] num new int[26];for (int i 0; i < s.length(); i) {num[s.charAt(i) - a];}StringBuffer sb new StringBuffer();for (in…...

Taro学习记录

一、安装taro-cli 二、项目文件 三、项目搭建 1、Eslint配置 在项目生成的 .eslintrc 中进行配置 {"extends": ["taro/react"], //一个配置文件&#xff0c;可以被基础配置中的已启用的规则继承"parser": "babel/eslint-parser…...

Spring Cache框架详解

Spring Cache框架详解 Spring Cache是Spring框架提供的一个强大的缓存抽象层&#xff0c;旨在简化缓存技术的集成和使用。自Spring 3.1版本开始&#xff0c;Spring Cache就被引入以支持在Spring应用程序中添加缓存功能。随着Spring版本的迭代&#xff0c;Spring Cache的功能日…...

解决Html iframe 内嵌video标签导致视频无法全屏展示的问题

原因&#xff1a; 由于浏览器的安全策略所限制的。为了防止恶意网站利用全屏播放功能进行滥用或欺骗用户&#xff0c;浏览器对iframe中的视频播放做了限制。 在iframe标签中播放视频时&#xff0c;浏览器会根据安全策略阻止视频全屏播放。这是因为iframe标签中的内容被认为是第…...

谷粒商城实战笔记-110~114-全文检索-ElasticSearch-查询

文章目录 一&#xff0c;110-全文检索-ElasticSearch-进阶-两种查询方式二&#xff0c;111-全文检索-ElasticSearch-进阶-QueryDSL基本使用&match_all三&#xff0c;112-全文检索-ElasticSearch-进阶-match全文检索四&#xff0c;113-全文检索-ElasticSearch-进阶-match_ph…...

【开源】嵌入式Linux(IMX6U)应用层综合项目(1)--云平台调试APP

目录 1.简介 1.1功能介绍 1.2技术栈介绍 1.3演示视频 1.4硬件介绍 2.软件设计 2.1连接阿里云 2.2云平台调试UI 2.3Ui_main.c界面切换处理文件 2.4.main函数 3.结尾&#xff08;附网盘链接&#xff09; 1.简介 此文章并不是教程&#xff0c;只能当作笔者的学习分享&…...

AI人工智能分析王楚钦球拍被踩事件的真相

在2024年巴黎奥运会乒乓球混双决赛的热烈氛围中&#xff0c;中国队王楚钦与孙颖莎以出色的表现夺得金牌&#xff0c;然而&#xff0c;赛后发生的一起意外事件——王楚钦的球拍被踩坏&#xff0c;引起了广泛关注和热议。为了探寻这一事件的真相&#xff0c;我们可以借助AI人工智…...

C++客户端Qt开发——多线程编程(一)

多线程编程&#xff08;一&#xff09; ①QThread 在Qt中&#xff0c;多线程的处理一般是通过QThread类来实现。 QThread代表一个在应用程序中可以独立控制的线程&#xff0c;也可以和进程中的其他线程共享数据。 QThread对象管理程序中的一个控制线程。 run() 线程的入口…...

安装pnpm

安装pnpm&#xff08;Performant npm&#xff09;&#xff0c;即高性能的npm包管理工具&#xff0c;可以通过多种方式进行。以下是详细的安装步骤&#xff1a; 一、通过npm全局安装 打开命令行工具&#xff1a;在你的计算机上打开命令行工具&#xff0c;例如Windows的CMD、Pow…...

CSS平移实现双开门效果

CSS平移实现双开门效果 一共要三张图片&#xff0c;一张作为父级背景&#xff0c;两张为兄弟左右布局 父子结构布局 一张作为父级背景&#xff0c;两张为兄弟左右布局。之后添加鼠标悬停效果&#xff0c;两张子图分别从左右平移 [外链图片转存失败,源站可能有防盗链机制,建议…...

3096. 得到更多分数的最少关卡数目

3096. 得到更多分数的最少关卡数目 题目链接&#xff1a;3096. 得到更多分数的最少关卡数目 代码如下&#xff1a; class Solution { public:int minimumLevels(vector<int>& possible) {int s0;//两个玩家能得到的分数和for(int x:possible){sx0?-1:1;}int t0;/…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...

通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器

拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件&#xff1a; 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...

【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道

文/法律实务观察组 在债务重组领域&#xff0c;专业机构的核心价值不仅在于减轻债务数字&#xff0c;更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明&#xff0c;合法债务优化需同步实现三重平衡&#xff1a; 法律刚性&#xff08;债…...

热烈祝贺埃文科技正式加入可信数据空间发展联盟

2025年4月29日&#xff0c;在福州举办的第八届数字中国建设峰会“可信数据空间分论坛”上&#xff0c;可信数据空间发展联盟正式宣告成立。国家数据局党组书记、局长刘烈宏出席并致辞&#xff0c;强调该联盟是推进全国一体化数据市场建设的关键抓手。 郑州埃文科技有限公司&am…...

[USACO23FEB] Bakery S

题目描述 Bessie 开了一家面包店! 在她的面包店里&#xff0c;Bessie 有一个烤箱&#xff0c;可以在 t C t_C tC​ 的时间内生产一块饼干或在 t M t_M tM​ 单位时间内生产一块松糕。 ( 1 ≤ t C , t M ≤ 10 9 ) (1 \le t_C,t_M \le 10^9) (1≤tC​,tM​≤109)。由于空间…...

STM32标准库-ADC数模转换器

文章目录 一、ADC1.1简介1. 2逐次逼近型ADC1.3ADC框图1.4ADC基本结构1.4.1 信号 “上车点”&#xff1a;输入模块&#xff08;GPIO、温度、V_REFINT&#xff09;1.4.2 信号 “调度站”&#xff1a;多路开关1.4.3 信号 “加工厂”&#xff1a;ADC 转换器&#xff08;规则组 注入…...

ArcGIS Pro+ArcGIS给你的地图加上北回归线!

今天来看ArcGIS Pro和ArcGIS中如何给制作的中国地图或者其他大范围地图加上北回归线。 我们将在ArcGIS Pro和ArcGIS中一同介绍。 1 ArcGIS Pro中设置北回归线 1、在ArcGIS Pro中初步设置好经纬格网等&#xff0c;设置经线、纬线都以10间隔显示。 2、需要插入背会归线&#xf…...