线程状态到底是5种还是六种?傻傻分不清楚

news2025/2/25 17:27:03

目录

从操作系统层面上描述线程状态

从javaAPI层面上理解线程的6种状态

线程的状态转换.

NEW --> RUNNABLE

1.RUNNABLE <--> WAITING

2.RUNNABLE <--> WAITING

3.RUNNABLE <--> WAITING

1.RUNNABLE <--> TIMED_WAITING

2.RUNNABLE <--> TIMED_WAITING

3. RUNNABLE <--> TIMED_WAITING

4.RUNNABLE <--> TIMED_WAITING

RUNNABLE <--> BLOCKED

RUNNABLE <--> TERMINATED


从操作系统层面上描述线程状态

  • 初始状态 : 仅仅是语言层面创建了线程对象,还没有与操作系统相关联.比如new 了一个Thread对象还没有调用start方法
  • 可运行状态 : 也可以理解为就绪状态,该线程已经被创建了,与操作系统相关联,可以由CPU调度,但是线程调度器还没有给该线程分配CPU时间片
  • 运行状态 : 给该线程分配了CPU时间片,线程处于正在运行的状态
    • 这里运行状态和可运行状态是能进行上下文切换的,当CPU时间片用完了,线程就会从运行状态变为可运行状态.,导致线程上下文切换
  • 阻塞状态 : 该线程调用了一些阻塞API,如BIO读写文件,这时该线程实际不会用到CPU,就会导致上下文切换,从运行状态变为阻塞状态.线程调度器不会分配给[阻塞状态线程]CPU时间片的,但是会分配给可运行状态的线程. 当读写文件操作完毕,会由操作系统来唤醒阻塞状态的线程, 就会从阻塞状态变为可运行状态
  • 终止状态 : 当当前线程的所有代码执行完成之后,表示线程已经执行完毕,生命周期已经结束了,不会再转换为其他状态.

从javaAPI层面上理解线程的6种状态

6种状态是JavaAPI层面上的.

根据Thread.State 枚举 ,分为6种状态.

  • NEW : 仅仅是语言层面创建了线程对象,还没有与操作系统相关联.比如new 了一个Thread对象还没有调用start方法
  • RUNNABLE : JavaAPI层面上状态涵盖了操作系统层面的[可运行状态],[运行状态] 和[阻塞状态]
  • 阻塞状态在Java里面细分为 BLOKED,WAITING,TIMED_WAITING
  • BLOKED : 当t线程调用synchronized(obj) 获取对象锁时竞争失败,会进入BLOCKED状态
  • WAITING : 当调用线程的join方法,LockSupport.park()方法或者用synchronized(obj)获取了对象锁后,调用obj.wait()方法时.
  • TIMED_WAITING : 当用synchronized获取对象锁后,调用wait(long n)方法时候,当调用join(long n) ,调用sleep(long n),或者调用LockSupport的有时限的方法
  • TERMINATED : 当当前线程的所有代码执行完成之后,表示线程已经执行完毕,生命周期已经结束了,不会再转换为其他状态.

利用Java代码来演示一下JavaAPI层面的6种状态

@Slf4j(topic = "c.TestState")
public class TestState {

    public static void main(String[] args) {
        //NEW 状态 -> 没有调用start方法->只创建了线程对象没有启动该线程
        Thread t1 = new Thread(() -> {
            log.debug("running...");
        },"t1");
        //Runnable状态中的可运行状态
        Thread t2 = new Thread(() -> {
            while(true) {

            }
        },"t2");
        //TIMED_WAITING状态
        Thread t3 = new Thread(()->{
            synchronized (TestState.class) {
                try {
                    Thread.sleep(100000000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"t3");
        //WAITING状态
        Thread t4 = new Thread(()->{
            try {
                t2.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t4");
        //TERMINATED->终止状态
        Thread t5 = new Thread(()->{
           log.debug("running....");
        },"t5");
        //BLOCKED 状态
        Thread t6 = new Thread(()->{//后获取到锁
           synchronized (TestState.class) {
               log.debug("running");
           }
        },"t6");
        t2.start();
        t3.start();
        t4.start();
        t5.start();
        t6.start();
        System.out.println("t1 : " + t1.getState());
        System.out.println("t2 : " + t2.getState());
        System.out.println("t3 : " + t3.getState());
        System.out.println("t4 : " + t4.getState());
        System.out.println("t5 : " + t5.getState());
        System.out.println("t6 : " + t6.getState());
    }
}

线程的状态转换.

NEW --> RUNNABLE

当调用了 t.start()方法的时候,由NEW --> RUNNABLE

1.RUNNABLE <--> WAITING

t线程用synchronized(obj) 获取了对象锁之后

  • 调用了obj.wait()方法的时候,t线程就从 RUNNABLE --> WAITING
  • 调用了 obj.notify() ,obj.notifyAll() ,t.interrupt() 时候
    • 竞争锁成功,t线程从 WAITING --> RUNNABLE
    • 竞争锁失败,t线程从 WAITING --> BLOCKED

比如两个线程竞争同一把锁,其中主线程使用notifyAll把它们全唤醒,那必然有一个线程竞争锁成功从WAITING --> RUNNABLE,必然有一个线程竞争锁失败从WAITING --> BLOCKED

2.RUNNABLE <--> WAITING

  • 当线程调用 t.join() 方法时,当前线程从 RUNNABLE --> WAITING
  • t线程运行结束,或者调用当前线程的interrupt()方法的时候,当前线程就从WAITING-->RUNNABLE状态

3.RUNNABLE <--> WAITING

  • 当前线程调用LockSupport.park()方法的时候会让当前线程从RUNNABLE-->WAITING
  • 当调用LockSupport.unpark方法或者调用线程的interrupt(),会让目标线程从WAITING-->RUNNABLE

1.RUNNABLE <--> TIMED_WAITING

当t线程调用了synchronized(obj) 获取了对象锁后

  • 调用obj.wait(long n)方法时,t线程从RUNNABLE --> TIMED_WAITING
  • 当t线程等待时间超过了n毫秒,或调用obj.notify(),obj.notifyAll(),t.interrupt() 时
    • 竞争锁成功,t 线程从 TIMED_WAITING --> RUNNABLE
    • 竞争锁失败,t 线程从 TIMED_WAITING --> BLOCKED

2.RUNNABLE <--> TIMED_WAITING

  • 当前线程调用 t.join(long n) 方法时,当前线程从 RUNNABLE --> TIMED_WAITING
  • 当前线程等待时间超过了 n 毫秒,或t 线程运行结束,或调用了当前线程的 interrupt() 时,当前线程从TIMED_WAITING --> RUNNABLE


3. RUNNABLE <--> TIMED_WAITING

  • 当前线程调用 Thread.sleep(long n) ,当前线程从 RUNNABLE --> TIMED_WAITING
  • 当前线程等待时间超过了 n 毫秒,当前线程从 TIMED_WAITING --> RUNNABLE


4.RUNNABLE <--> TIMED_WAITING

  • 当前线程调用 LockSupport.parkNanos(long nanos) 或 LockSupport.parkUntil(long millis) 时,当前线程从 RUNNABLE --> TIMED_WAITING
  • 调用 LockSupport.unpark(目标线程) 或调用了线程 的 interrupt() ,或是等待超时,会让目标线程从TIMED_WAITING--> RUNNABLE

RUNNABLE <--> BLOCKED

  • 当t线程用synchronized(obj)获取了对象锁时如果竞争失败就会从 RUNNABLE-->BLOCKED
  • 持有obj锁线程的同步代码块执行完毕,会唤醒该对向上的所有BLOKED的线程,如果其中t线程竞争成功,从BLOKED-->RUNNABLE ,其他失败的线程仍然是 BLOCKED.

RUNNABLE <--> TERMINATED

当当前线程的所有代码执行完成之后,表示线程已经执行完毕,生命周期已经结束了,不会再转换为其他状态.

参考 : 黑马程序员 Java并发编程视频

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

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

相关文章

开源天气时钟项目删减和更新

开源天气时钟项目删减和更新&#x1f4cc;原项目开源地址&#xff1a;https://gitee.com/liuzewen/ESP8266-SSD1306-Watch-mini ✨本文只针对Arduino IDE平台代码进行删减和更新。 &#x1f4fa;按键菜单功能 &#x1f33c;天气时钟功能整体架构描述 代码中所使用的库&…

【MySQL】十,SQL执行流程

MySQL中的SQL执行流程 MySQL的查询流程 查询缓存 Server 如果在查询缓存中发现了这条 SQL 语句&#xff0c;就会直接将结果返回给客户端 如果没有&#xff0c;就进入到解析阶段&#xff08;MySQL 8.0 已经废弃了查询缓存功能&#xff09;。 解析器 在解析器中对 SQL 语句进行…

36、基于STM32的电子闹钟(DS1302)

编号&#xff1a;36 基于STM32的电子闹钟&#xff08;DS1302&#xff09; 功能描述&#xff1a; 本设计由STM32单片机液晶1602按键DS1302时钟模块声光报警模组成。 1、采用STM32F103最小系统。 2、利用DS1302芯片提供时钟信号 3、液晶1602实时显示年月日、时分秒、星期等信息…

java线程池原理

背景&#xff1a;为什么需要线程池java中的线程池是运用场景最多的并发框架&#xff0c;几乎所有需要异步或并发执行任务的程序都可以使用线程池。在开发过程中&#xff0c;合理的使用线程池能够带来3个好处。降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消…

(1分钟了解)SLAM的七大问题:地图表示、信息感知、数据关联、定位与构图、回环检测、深度、绑架

编辑切换为居中添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09;SLAM问题也被称为是CML问题。编辑切换为居中添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09;编辑切换为居中添加图片注释&#xff0c;不超过 140 字&#xff08;可选&…

(JMLR-2019)NAS综述鼻祖-神经架构搜索:一项调查

神经架构搜索&#xff1a;一项调查 paper题目&#xff1a;Neural Architecture Search: A Survey paper是博世人工智能中心发表在JMLR 2019的工作 paper链接&#xff1a;地址 Abstract 过去几年&#xff0c;深度学习在图像识别、语音识别和机器翻译等各种任务上取得了显着进步…

【C++】stl---vector的模拟实现(超级详细,万字详解)

文章目录前言vector的成员属性构造函数size函数cacpcity函数begin和end函数reserve函数insert函数push_back函数[]操作符重载析构函数拷贝构造函数赋值操作符重载erase函数pop_back反向迭代器反向迭代器模板反向迭代器的构造函数运算符重载- -运算符重载*引用操作符重载&#x…

Spring AOP 企业级应用 - 统一功能处理

1.统一用户登录权限效验统一用户登录权限效验使用传统的 AOP 能否解决问题呢 ? Component Aspect // 标识当前类为一个切面 public class LoginAOP {// 定义切点 (拦截的规则) - 拦截 UserController 中的所有方法Pointcut("execution(* com.example.demo.controller.Tes…

React Hooks 基础、实现、原理

React Hooks 基础、实现、原理题外话为什么要有Hooks&#xff1f;但是Class Component 的用法也有缺陷&#xff1a;1.组件复用变的困难2.JavaScript本身的缺陷函数式React HooksuseStateuseEffectuseCallback、useMemouseReducer最后题外话 2023了&#xff0c;新年快乐&#x…

【javascript】DOM 案例

点击查看密码 &#xff1a;就是把type等于password改为text即可&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><…

电力系统强大的Gurobi 求解器的学习(PythonMatlab)

到底有多强大&#xff0c;看看就知道&#xff0c;必须&#x1f44d;&#x1f44d;&#x1f44d;&#xff1a; 目录 1 概述 2 算例理解【Python】 2.1 算例1——详细入门 2.2 算例2——一般线性规划问题 2.3 算例3——非凸问题 3 算例升级【Matlab】 3.1 模型 3.2 电力系统…

Python2.x 与 3​​.x 版本到底有啥区别?

嗨害大家好鸭&#xff01;我是小熊猫~ 今天给大家带来一点小干货~ 很多人对于python的版本有些许疑问&#xff0c; 今天就来给大家说说看~ Python学习资料电子书点击此处跳转文末名片 Python 的 3​​.0 版本&#xff0c;常被称为 Python 3000&#xff0c;或简称 Py3k。 相对…

Mybatis-Plus“读-批量写-读”数据不一致的问题分享

在日常开发过程中&#xff0c;时常会遇到一个如下场景&#xff1a; 根据条件x&#xff0c;读取表A&#xff0c;得到多行数据&#xff1b;遍历读取到的数据&#xff0c;对条件x以外的字段进行修改&#xff0c;并进行保存&#xff1b;&#xff08;重点&#xff09;修改后&#x…

基础算法(七)——离散化

离散化 介绍 这里的离散化&#xff0c;特指整数的、保序的离散化 有些题目可能需要以数据作为下标来操作&#xff0c;但题目给出的数据的值比较大&#xff0c;但是数据个数比较小。此时就需要将数据映射到和数据个数数量级相同的区间&#xff0c;这就是离散化&#xff0c;即…

基于imx6ull第一个Linux驱动

在编译第一个驱动之前&#xff0c;需要把基本的环境准备好&#xff0c;可以参照这两篇文章&#xff1a;https://wlink.blog.csdn.net/article/details/128590747https://wlink.blog.csdn.net/article/details/128591216我们之前写过一个基于ubuntu最基本的字符设备驱动&#xf…

关于固态硬盘冷数据掉速问题解决方案

20230107 By wdhuag 前言&#xff1a; 我有一个西数蓝盘500G固态&#xff0c;系统盘&#xff0c;一年没开机&#xff0c;这个月开机后发现系统很卡&#xff0c;持续读取假死严重。测试没有坏块&#xff0c;网上说的是冷数据掉速问题。 参考&#xff1a; 如何看待西数/闪迪多…

排序算法:插入、希尔、选择、冒泡

目录 一.插入排序 1.算法描述&#xff1a; 2.实现思路&#xff1a; 3.时间复杂度&#xff1a; 代码如下&#xff1a; 二.希尔排序 &#xff08;插入排序的优化升级&#xff09; 1.算法描述&#xff1a; 2.实现思路&#xff1a; 3.时间复杂度&#xff1a; 代码如下&a…

【算法笔记】最近公共祖先(LCA)问题求解——倍增算法

0. 前言 最近公共祖先简称 LCA&#xff08;Lowest Common Ancestor&#xff09;。两个节点的最近公共祖先&#xff0c;就是这两个点的公共祖先里面&#xff0c;离根最远的那个。 这种算法应用很广泛&#xff0c;可以很容易解决树上最短路等问题。 为了方便&#xff0c;我们记…

星光不负赶路人|2022年终总结

时间真快&#xff0c;转眼又是年末。整理一篇文章来给自己好好做一次年终盘点&#xff0c;本着陈述事实&#xff0c;提炼精华&#xff0c;总结不足的思路&#xff0c;给自己这一年的工作、生活、成长画个句号。 工作 &#x1f3e2; 从经海路到中关村 去年换了工作&#xff0c…

Java设计模式中的创建者模式/单例模式是啥?单例模式其中的饿汉式与懒汉式又是啥?又可以用在哪些地方

继续整理记录这段时间来的收获&#xff0c;详细代码可在我的Gitee仓库SpringBoot克隆下载学习使用&#xff01; 4. 创建者模式 4.1 特点 使用者不需要知道对象的创建细节 4.2 单例模式 4.2.1使用场景 单例类&#xff1a;且仅能创建一个实例类访问类&#xff1a;使用单例类…