一个线程,从“生”到“死”经历的过程
本文分享自华为云社区《面试必问 | 一个线程从创建到消亡要经历哪些阶段?》,作者: 冰 河。
今天,我们就结合 操作系统线程和编程语言线程 再次深入探讨线程的生命周期问题,线程的生命周期其实没有我们想象的那么简单!!
理解线程的生命周期本质上理解了生命周期中各个节点的状态转换机制就可以了。接下来,我们分别就 通用线程生命周期和Java语言的线程生命周期 分别进行详细说明。
通用的线程生命周期
通用的线程生命周期总体上可以分为五个状态:初始状态、可运行状态、运行状态、休眠状态和终止状态。
我们可以简单的使用下图来表示这五种状态。
初始状态
线程已经被创建,但是不允许分配CPU执行。需要注意的是:这个状态属于编程语言特有,这里指的线程已经被创建,仅仅指在编程语言中被创建,在操作系统中,并没有创建真正的线程。
可运行状态
线程可以分配CPU执行。此时,操作系统中的线程被成功创建,可以分配CPU执行。
运行状态
当操作系统中存在空闲的CPU,操作系统会将这个空闲的CPU分配给一个处于可运行状态的线程,被分配到CPU的线程的状态就转换成了运行状态
休眠状态
运行状态的线程调用一个阻塞的API(例如,以阻塞的方式读文件)或者等待某个事件(例如,等待某个条件变量等),线程的状态就会转换到休眠状态。**此时线程会释放CPU资源,休眠状态的线程没有机会获得CPU的使用权。**一旦等待的条件出现,线程就会从休眠状态转换到可运行状态。
终止状态
线程执行完毕或者出现异常就会进入终止状态,终止状态的线程不会切换到其他任何状态,这也意味着线程的生命周期结束了。
以上就是通用的线程生命周期,下面,我们再看对比看下Java语言中的线程生命周期。
Java中的线程生命周期
Java中的线程生命周期总共可以分为六种状态:初始化状态(NEW)、可运行/运行状态(RUNNABLE)、阻塞状态(BLOCKED)、无时限等待状态(WAITING)、有时限等待状态(TIMED_WAITING)、终止状态(TERMINATED)。
需要大家重点理解的是:虽然Java语言中线程的状态比较多,但是,其实在操作系统层面,Java线程中的阻塞状态(BLOCKED)、无时限等待状态(WAITING)、有时限等待状态(TIMED_WAITING)都是一种状态,即通用线程生命周期中的休眠状态。也就是说,只要Java中的线程处于这三种状态时,那么,这个线程就没有CPU的使用权。
理解了这些之后,我们就可以使用下面的图来简单的表示Java中线程的生命周期。
我们也可以这样理解阻塞状态(BLOCKED)、无时限等待状态(WAITING)、有时限等待状态(TIMED_WAITING),它们是导致线程休眠的三种原因!
接下来,我们就看看Java线程中的状态是如何转化的。
RUNNABLE与BLOCKED的状态转换
只有一种场景会触发这种转换,就是线程等待synchronized隐式锁。synchronized修饰的方法、代码块同一时刻只允许一个线程执行,其他的线程则需要等待。
此时,等待的线程就会从RUNNABLE状态转换到BLOCKED状态。当等待的线程获得synchronized隐式锁时,就又会从BLOCKED状态转换到RUNNABLE状态。
这里,需要大家注意:线程调用阻塞API时,在操作系统层面,线程会转换到休眠状态。但是在JVM中,Java线程的状态不会发生变化,也就是说,Java线程的状态仍然是RUNNABLE状态。
JVM并不关心操作系统调度相关的状态,在JVM角度来看,等待CPU使用权(操作系统中的线程处于可执行状态)和等待IO操作(操作系统中的线程处于休眠状态)没有区别,都是在等待某个资源,所以,将其都归入了RUNNABLE状态。
我们平时所说的Java在调用阻塞API时,线程会阻塞,指的是操作系统线程的状态,并不是Java线程的状态。
RUNNABLE与WAITING状态转换
线程从RUNNABLE状态转换成WAITING状态总体上有三种场景。
场景一
获得synchronized隐式锁的线程,调用无参的Object.wait()方法。此时的线程会从RUNNABLE状态转换成WAITING状态。
场景二
调用无参数的Thread.join()方法。其中join()方法是一种线程的同步方法。例如,在threadA线程中调用threadB线程的join()方法,则threadA线程会等待threadB线程执行完。
而threadA线程在等待threadB线程执行的过程中,其状态会从RUNNABLE转换到WAITING。当threadB执行完毕,threadA线程的状态则会从WAITING状态转换成RUNNABLE状态。
场景三
调用LockSupport.park()方法,当前线程会阻塞,线程的状态会从RUNNABLE转换成WAITING。
调用LockSupport.unpark(Thread thread)可唤醒目标线程,目标线程的状态又会从WAITING状态转换到RUNNABLE。
RUNNABLE与TIMED_WAITING状态转换
总体上可以分为五种场景。
场景一
调用带超时参数的Thread.sleep(long millis)方法;
场景二
获得synchronized隐式锁的线程,调用带超时参数的Object.wait(long timeout)参数;
场景三
调用带超时参数的Thread.join(long millis)方法;
场景四
调用带超时参数的LockSupport.parkNanos(Object blocker, long deadline)方法;
场景五
调用带超时参数的LockSuppor.parkUntil(long deadline)方法。
从NEW到RUNNABLE状态
Java刚创建出来的Thread对象就是NEW状态,创建Thread对象主要有两种方法,一种是继承Thread对象,重写run()方法;另一种是实现Runnable接口,重写run()方法。
注意:这里说的是创建Thread对象的方法,而不是创建线程的方法,创建线程的方法包含创建Thread对象的方法。
继承Thread对象
public class ChildThread extends Thread{ @Override public void run(){ //线程中需要执行的逻辑 } } //创建线程对象 ChildThread childThread = new ChildThread();
实现Runnable接口
public class ChildRunnable implements Runnable{ @Override public void run(){ //线程中需要执行的逻辑 } } //创建线程对象 Thread childThread = new Thread(new ChildRunnable());
处于NEW状态的线程不会被操作系统调度,因此也就不会执行。Java中的线程要执行,就需要转换到RUNNABLE状态。从NEW状态转换到RUNNABLE状态,只需要调用线程对象的start()方法即可。
//创建线程对象 Thread childThread = new Thread(new ChildRunnable()); //调用start()方法使线程从NEW状态转换到RUNNABLE状态 childThread.start();
RUNNABLE到TERMINATED状态
线程执行完run()方法后,或者执行run()方法的时候抛出异常,都会终止,此时为TERMINATED状态。如果我们需要中断run()方法,可以调用interrupt()方法。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
bootx-platform 1.3.6 权限安全控制增强版本
项目介绍 项目地址:https://gitee.com/bootx/bootx-platform,https://gitee.com/bootx/dax-pay(全新开源支付网关)非常欢迎看看项目介绍留以及个Star呀🤺🤺🤺 基于 Spring Boot 框架生态打造,针对单体式应用进行专门设计,同时做好模块切分,兼顾快速适应分布式改造,其设计准则是切分功能,划分模块,不同模块之间间可能减少耦合,更好的适应实际中各类不同项目开发时的侧重点。设计目标是将日常项目开发中,尤其是中小型项目中的一些高频诉求进行覆盖,还有一些主流业务场景进行实现,对这些高频但并不高大上的需要进行解决。同时核心源码和文档开源,不需要进行额外操作就可以直接获取源码和文档,以及查看演示环境。 应用场景 适用于一些中小型项目开发中,内含各类开箱即用的组件,以及对一些常见领域提供一些默认的解决方式,供应商关系管理、合同管理、人力资源管理、项目管理、资产管理、订单管理、电商商城等领域;相较于一些使用广泛的开源版本平台,对其一些不包含在开源版的付费功能进行了开源实现,适合一些较低预算,或是 Demo 验证开发等无法有充...
- 下一篇
智能制造一体化 v3.12.2 发布,ERP 手机端更新
智能制造一体化管理系统[SpringBoot2 - 快速开发平台],适用于制造业、建筑业、汽车行业、互联网、教育、政府机关等机构的管理。包含文件在线操作、工作日志、多班次考勤、CRM、ERP 进销存、项目管理、EHR、拖拽式生成问卷、日程、笔记、工作计划、行政办公、薪资模块、动态表单、知识库、公告模块、企业论坛、云售后模块、生产模块、系统模块化同步模块等多种复杂业务功能。 有一些小伙伴很好奇最近更新的内容和智能制造有什么关系? 答:目前 Skyeye 整体在做重构,优先从底层的一些功能开始,所以现在大家看到的和智能制造的联系不是很大,也希望大家能够理解,一个大型的智能制造对底层的依赖性也是非常高的。 智能制造一体化 v3.12.2 发布,手机端完成以下内容的代码编写: 采购订单、采购入库、采购退货 销售订单、销售出库、销售退货 零售出库、零售退货 其他入库、其他出库、拆分单、组装单、调拨单 解决若干组件加载的问题 Skyeye 具备低代码、快捷开发、可视化设计、微服务等特点,方便客户二次开发,极大的提高了开发效率。 erp:https://gitee.com/doc_wei01/erp...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7安装Docker,走上虚拟化容器引擎之路
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS关闭SELinux安全模块
- CentOS7,CentOS8安装Elasticsearch6.8.6
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- Linux系统CentOS6、CentOS7手动修改IP地址
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS8安装Docker,最新的服务器搭配容器使用
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能