Java多线程--线程的生命周期

文章目录

  • 一、JDK1.5之前:5种状态
    • 五种状态
      • 1、新建
      • 2、就绪
      • 3、运行
      • 4、阻塞
      • 5、死亡
  • 二、JDK1.5及之后:六种状态

Java语言使用 Thread类及其子类的对象来表示 线程,在它的一个完整的生命周期中通常要经历如下一些状态。

一、JDK1.5之前:5种状态

线程的生命周期有五种状态:新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)、死亡(Dead)。

CPU需要在多条线程之间切换,于是线程状态会多次在运行、阻塞、就绪之间切换。

image.png

注意:是一些方法的调用,使得线程从一种状态切换到另外一种状态。

现在说的是方法的执行导致状态的改变,以后会说到状态变化使得一些方法会执行。

五种状态

1、新建

🍰new了一个线程的对象,new完之后这个线程就“新建”了。

当一个Thread类或其子类的对象声明并创建时,新生的线程对象处于新建状态

此时它和其他Java对象一样,仅仅由JVM为其分配了内存,并初始化了实例变量的值

此时的线程对象并没有任何线程的动态特征,程序也不会执行它的线程体run()

2、就绪

🍰“就绪”就是CPU可以随时去执行它了。从“新建”到“就绪”需要调用start()方法。

若是新建完之后不调用start()方法,这个线程就始终不会被CPU执行。

但是当线程对象调用了start()方法之后,就不一样了,线程就从新建状态转为就绪状态

JVM会为其创建方法调用栈和程序计数器,当然,处于这个状态中的线程并没有开始运行,只是表示已具备了运行的条件,随时可以被调度。至于什么时候被调度,取决于JVM里线程调度器的调度。

🗳️注意

程序只能对新建状态的线程调用start(),并且只能调用一次

如果对非新建状态的线程,如已启动的线程或已死亡的线程调用start()都会报错IllegalThreadStateException异常。

3、运行

🍰位于“就绪态”的线程被CPU选择执行,这个线程就处于了“运行态”。

如果处于就绪状态的线程获得了CPU资源时,开始执行run()方法的线程体代码,则该线程处于运行状态

如果计算机只有一个CPU核心,在任何时刻只有一个线程处于运行状态;如果计算机有多个核心,将会有多个线程并行(Parallel)执行。

当然,美好的时光总是短暂的,而且CPU讲究雨露均沾。

对于抢占式策略的系统而言,系统会给每个可执行的线程一个小时间段来处理任务,当该时间用完,系统会剥夺该线程所占用的资源,让其回到就绪状态等待下一次被调度。此时其他线程将获得执行机会,而在选择下一个线程时,系统会适当考虑线程的优先级

“运行”是我们希望看到的,就是执行run()方法了。

🗳️注意

①线程获得CPU的执行权:从“就绪”到“运行”。(当CPU执行到这个线程,而这个线程又刚好是就绪状态,这个线程就会被CPU执行)

②线程失去了CPU的执行权:从“运行”到“就绪”。(当线程主动调用yield()方法,就是指这个线程主动要去释放CPU执行权,这个线程会进入就绪状态,注意不是阻塞状态)

4、阻塞

🍰当在运行过程中的线程遇到如下情况时,会让出 CPU 并临时中止自己的执行,进入阻塞状态

  • 线程调用了sleep()方法,主动放弃所占用的CPU资源;
  • 线程试图获取一个同步监视器,但该同步监视器正被其他线程持有;
  • 线程执行过程中,同步监视器调用了wait(),让它等待某个通知(notify);
  • 线程执行过程中,同步监视器调用了wait(time)
  • 线程执行过程中,遇到了其他线程对象的加塞(join);
  • 线程被调用suspend方法被挂起(已过时,因为容易发生死锁)

当前正在执行的线程被阻塞后,其他线程就有机会执行了。

针对如上情况,当发生如下情况时会解除阻塞,让该线程重新进入就绪状态,等待线程调度器再次调度它:

  • 线程的sleep()时间到;
  • 线程成功获得了同步监视器
  • 线程等到了通知(notify);
  • 线程wait的时间到了;
  • 加塞的线程结束了;
  • 被挂起的线程又被调用了resume恢复方法(已过时,因为容易发生死锁)

当线程处于“阻塞”状态了,不会一直阻塞,一定会到就绪状态,否则程序就会有问题,他需要回到 “就绪”状态,然后被CPU分配并执行,最终“死亡”。

5、死亡

线程会以以下三种方式之一结束,结束后的线程就处于死亡状态

  • run()方法执行完成,线程正常结束;
  • 线程执行过程中抛出了一个未捕获的异常(Exception)或错误(Error);
  • 直接调用该线程的stop()来结束该线程(已过时)

“死亡”状态无法回到“运行”状态。

二、JDK1.5及之后:六种状态

java.lang.Thread.State枚举类中这样定义:

public enum State {	//里面的对象表示线程的生命周期NEW,	//新建RUNNABLE,	//就绪+运行BLOCKED,	//阻塞WAITING,	//等待TIMED_WAITING,	//有指定时间的等待TERMINATED;		//死亡
}

State是Thread类中的内部类,还是一个枚举类。

🍰详细介绍

image.png

<1> NEW(新建):线程刚被创建,但是并未启动。还没调用start方法。

还是JDK1.5之前版本的“新建”。

<2> RUNNABLE(可运行):这里没有区分就绪和运行状态。

因为对于Java对象来说,只能标记为可运行,至于什么时候运行,不是JVM来控制的了,是OS来进行调度的,而且时间非常短暂,因此对于Java对象的状态来说,无法区分。

“就绪”又可以叫“准备”,“准备”和“运行”合在一起,称为Runnable。

这是一个可以运行的状态,不区分是准备好了还是正在运行了。

<3> Teminated(被终止):表明此线程已经结束生命周期,终止运行。

还是JDK1.5之前版本的“死亡”。

<4> 重点说明,根据Thread.State的定义,根据不同方法的调用,将阻塞状态分为三种BLOCKEDWAITINGTIMED_WAITING

  • BLOCKED(锁阻塞):在API中的介绍为:一个正在阻塞、等待一个监视器锁(锁对象)的线程处于这一状态。只有获得锁对象的线程才能有执行机会。
    • 比如,线程A与线程B代码中使用同一锁,如果线程A获取到锁,线程A进入到Runnable状态,那么线程B就进入到Blocked锁阻塞状态。
  • TIMED_WAITING(计时等待):在API中的介绍为:一个正在限时等待另一个线程执行一个(唤醒)动作的线程处于这一状态。
    • 当前线程执行过程中遇到Thread类的sleepjoin,Object类的wait,LockSupport类的park方法,并且在调用这些方法时,设置了时间,那么当前线程会进入TIMED_WAITING,直到时间到,或被中断。
  • WAITING(无限等待):在API中介绍为:一个正在无限期等待另一个线程执行一个特别的(唤醒)动作的线程处于这一状态。
    • 当前线程执行过程中遇到遇到Object类的wait,Thread类的join,LockSupport类的park方法,并且在调用这些方法时,没有指定时间,那么当前线程会进入WAITING状态,直到被唤醒。
      • 通过Object类的wait进入WAITING状态的要有Object的notify/notifyAll唤醒;
      • 通过Condition的await进入WAITING状态的要有Condition的signal方法唤醒;
      • 通过LockSupport类的park方法进入WAITING状态的要有LockSupport类的unpark方法唤醒;
      • 通过Thread类的join进入WAITING状态,只有调用join方法的线程对象结束才能让当前线程恢复;

若wait()小括号里面没有写时间,这个就是无限等待,只能被notify()。

若wait()小括号里面写了时间,到了时间就会结束等待,叫做指定时间的等待。


🎲说明:当从WAITING或TIMED_WAITING恢复到Runnable状态时,如果发现当前线程没有得到监视器锁,那么会立刻转入BLOCKED状态。

image.png

我们在翻阅API的时候会发现Timed Waiting(计时等待) 与 Waiting(无限等待) 状态联系还是很紧密的,比如Waiting(无限等待) 状态中wait方法是空参的,而timed waiting(计时等待) 中wait方法是带参的。

这种带参的方法,其实是一种倒计时操作,相当于我们生活中的小闹钟,我们设定好时间,到时通知,可是如果提前得到(唤醒)通知,那么设定好时间在通知也就显得多此一举了,那么这种设计方案其实是一举两得。

如果没有得到(唤醒)通知,那么线程就处于Timed Waiting状态,直到倒计时完毕自动醒来;如果在倒计时期间得到(唤醒)通知,那么线程从Timed Waiting状态立刻唤醒。


【举例】

public class ThreadStateTest {public static void main(String[] args) throws InterruptedException {SubThread t = new SubThread();System.out.println(t.getName() + " 状态 " + t.getState());t.start();while (Thread.State.TERMINATED != t.getState()) {System.out.println(t.getName() + " 状态 " + t.getState());Thread.sleep(500);}System.out.println(t.getName() + " 状态 " + t.getState());}
}class SubThread extends Thread {@Overridepublic void run() {while (true) {for (int i = 0; i < 10; i++) {System.out.println("打印:" + i);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}break;}}
}

命令行演示:

image.png

关于这些方法,现在了解即可,后面慢慢介绍。

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

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

相关文章

搜狐新闻客户端使用Kotlin之后对JSON解析框架的探索

本文字数&#xff1a;7488字 预计阅读时间&#xff1a;45分钟 01 引言 自2017年Google发布Kotlin语言之后&#xff0c;Android开发由原来的Java开始向Kotlin过度&#xff0c;目前绝大部分Android开发岗位基本要求就是熟练使用Kotlin。事实上&#xff0c;很多有着多年历史的项目…

CAD-autolisp(二)——选择集、命令行设置对话框、符号表

目录 一、选择集1.1 选择集的创建1.2 选择集的编辑1.3 操作选择集 二、命令行设置对话框2.1 设置图层2.2 加载线型2.3 设置字体样式2.4 设置标注样式&#xff08;了解即可&#xff09; 三、符号表3.1 简介3.2 符号表查找3.2 符号表删改增 一、选择集 定义&#xff1a;批量选择…

【广度优先搜索】【拓扑排序】【C++算法】913. 猫和老鼠

作者推荐 【动态规划】【map】【C算法】1289. 下降路径最小和 II 本文涉及知识点 广度优先搜索 拓扑排序 逆推 LeetCode913. 猫和老鼠 两位玩家分别扮演猫和老鼠&#xff0c;在一张 无向 图上进行游戏&#xff0c;两人轮流行动。 图的形式是&#xff1a;graph[a] 是一个列…

List使用addAll()方法报错

当使用Arrays.asList方式创建出来的list&#xff0c;在使用addAll方法的时候报错如下&#xff1a; Exception in thread "main" java.lang.UnsupportedOperationException 这个问题记录下&#xff0c;以防以后忘记。 下面是代码 List<String> objects new A…

风口抓猪-借助亚马逊云科技EC2服务器即刻构建PalWorld(幻兽帕鲁)私服~~~持续更新中

Pocketpair出品的生存类游戏《幻兽帕鲁》最近非常火&#xff0c;最高在线人数已逼近200万。官方服务器亚历山大&#xff0c;游戏开发商也提供了搭建私人专用服务器的方案&#xff0c;既可以保证稳定的游戏体验&#xff0c;也可以和朋友一起联机游戏&#xff0c;而且还能自定义经…

LeetCode:1706. 球会落何处(Java 模拟)

目录 1706. 球会落何处 题目描述&#xff1a; 实现代码与解析&#xff1a; 原理思路&#xff1a; 1706. 球会落何处 题目描述&#xff1a; 用一个大小为 m x n 的二维网格 grid 表示一个箱子。你有 n 颗球。箱子的顶部和底部都是开着的。 箱子中的每个单元格都有一个对角线…

如何实现无公网IP实现远程访问MongoDB文件数据库

&#x1f4d1;前言 本文主要是如何实现无公网IP实现远程访问MongoDB文件数据库的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是青衿&#x1f947; ☁️博客首页&#xff1a;CSDN主页放风讲故事 &#x…

移动Web——平面转换-平移

1、平面转换-平移 取值 像素单位数值百分比&#xff08;参照盒子自身尺寸计算结果&#xff09;正负均可 技巧 translate()只写一个值&#xff0c;表示沿着X轴移动单独设置X或Y轴移动距离&#xff1a;translateX()或translateY() <!DOCTYPE html> <html lang"en&q…

53-JS之BOM,打开,关闭窗口,screen对象,history对象,location对象,工作区尺寸,滚动距离

1.简介 BOM(Browser Object Model)---浏览器对象模型,提供JS当中对浏览器的各种操作对象 1.1BOM与DOM 2.打开窗口window.open(URL,name,features) 2.1 URL字符串:地址网址文件源 2.2name:指target属性,规定在哪个窗口打开新的url链接 blank:打开一个新窗口 _parent…

MVC架构模式与三层架构

提示&#xff1a;博客中的图片来源于动力节点在B站的视频讲解。 MVC架构模式与三层架构 一、三层架构二、MVC&#xff08;model view controller&#xff09;1.MVC 架构的工作流程&#xff08;1&#xff09;JSP Servlet javabean实现MVC。&#xff08;2&#xff09;SSM&#…

Linux——文本编辑器Vim

Linux中的所有内容以文件形式管理&#xff0c;在命令行下更改文件内容&#xff0c;常常会用到文本编辑器。我们首选的文本编辑器是Vim&#xff0c;它是一个基于文本界面的编辑工具&#xff0c;使用简单且功能强大&#xff0c;更重要的是&#xff0c;Vim是所有Linux发行版本的默…

详解静态网页数据获取以及浏览器数据和网络数据交互流程

目录 前言 一、静态网页数据 二、网址通讯流程 1.DNS查询 2.建立连接 3.发送HTTP请求 4.服务器处理请求 5.服务器响应 6.渲染页面 7.页面交互 三、URL/POST/GET 1.URL 2.GET 形式 3.POST 形式 四.获取静态网页数据 前言 在网站设计领域&#xff0c;基于纯HTM…

机房及设备安全智慧监管AI+视频方案的设计和应用

一、背景分析 随着互联网的迅猛发展&#xff0c;机房及其配套设施的数量持续攀升&#xff0c;它们的运行状况对于企业运营效率和服务质量的影响日益显著。作为企业信息化的基石&#xff0c;机房的安全监测与管理的重要性不容忽视。它不仅关乎企业的稳定运营&#xff0c;同时也…

希尔排序-排序算法

前言 希尔排序固然很好&#xff0c;但是某些情况下&#xff0c;有很多缺点。例如下面这种情况&#xff1a; 9 之前的元素都已经有序&#xff0c;只有元素 1 和 2 的位置不对&#xff0c;使用插入排序几乎要移动整个数组的元素&#xff0c;效率很低。 这时候希尔排序横空出世&…

黑群晖显示真实的CPU型号和自定义CPU型号

黑群晖显示真实的CPU型号和自定义CPU型号 修改脚本执行脚本自定义显示的CPU型号 脚本的仓库地址:✈ 修改脚本 我的CPU型号是N100&#xff0c;这里因为架构识别有问题&#xff0c;所有CPU的型号后面会带一个UnKnown&#xff0c;感觉很别扭&#xff0c;所有修改了下脚本 if […

AcWing 2. 01背包问题(DP思想)

[题目概述] 有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。 第 i 件物品的体积是 v i v_i vi​&#xff0c;价值是 w i w_i wi​。 求解将哪些物品装入背包&#xff0c;可使这些物品的总体积不超过背包容量&#xff0c;且总价值最大。 输出最大价值。 输入格式 …

Vue组件之间的通信方式都有哪些

Vue组件之间的通信方式 组件间通信的概念组件间通信解决了什么组件间通信的分类 父子组件之间的通信兄弟组件之间的通信祖孙与后代组件之间的通信非关系组件间之间的通信 组件间通信的方案 props传递数据$emit 触发自定义事件refEventBusparent、rootattrs与listenersprovide …

Oracle分栏(非分页)查询

不知道Oracle怎么进行数据分栏(分栏: 因数据列过长, 部分数据作为新列显示). 在这里先记录一下粗浅的查询方法. 数据源例子: select 日用百货 as cat, 手电筒 as name, 20 as amount, 2024-01-27 as dt from dualunion allselect 餐饮美食 as cat, 鸡公煲 as name, 15.9 as amo…

SSEBop FEWS V6蒸散发ET年和月尺度数据分享

一、数据简介 SSEBOP FEWS V6是一个用于估算蒸散发&#xff08;evapotranspiration&#xff09;的模型或数据集。蒸散发是指地表和植物蒸发以及植物蒸腾的总和&#xff0c;是水循环中重要的组成部分。 SSEBOP FEWS V6是由美国地质调查局&#xff08;USGS&#xff09;开发的一…

Genome-wide association studies in R

全基因组关联&#xff08;GWA&#xff09;研究扫描整个物种基因组&#xff0c;寻找多达数百万个SNPs与特定感兴趣特征之间的关联。值得注意的是&#xff0c;感兴趣的性状实际上可以是归因于群体的任何类型的表型&#xff0c;无论是定性的&#xff08;例如疾病状态&#xff09;还…