并发-线程的 6 个状态(生命周期)

目录

状态解释

状态间的转化


状态解释

状态间的转化

  • 根据Thread类中定义的枚举类型State值,可以看出有6种状态:
  • 可以通过 Thread.getState 方法获得线程的状态
  • NEW(新建)New
  • 新建了Thread类对象,但是没有启动的线程
  • 尚未启动;已创建但是还没有启动的线程,比如new Thread后的线程,但是还没执行start方法
  • RUNNABLE(可运行状态,而不只是正在运行的)Runnable
  • 正在 JVM 中运行;或者正在等待操作系统的其他资源(比如处理器)
  • new后的线程,调用了start方法,此时的线程就是Runnable状态
  • 有些编程语言会把RUNNABLE分成2种情况:1-running和2-ready
  • 也就是处于此状态的线程有可能正在执行,也有可能正在等待着CPU为它分配执行时间(该线程已经获取了除CPU资源外的其他资源,等待获取CPU 资源后才会真正处于运行状态)
  • 以上2种在Java中都属于Runnable
  • 调用了start方法,不代表线程启动了,有可能还在队列中等待资源分配,还没被处理器执行
  • 拿到CPU运行后,同样也叫做Runnable状态
  • 运行时的线程,CPU资源被抢走了,此时线程还是处于Runnable状态,因为只要得到CPU,它就可以继续运行
  • Runnable既可以代表可运行的,也可以代表运行中的
  • BLOCKED(被阻塞) Blocked
  • 正在等待监视器锁(内部锁)的释放
  • 当一个线程进入到被synchronized修饰的代码块时,而且该锁被其他线程拿走了,那么这个线程的状态就是Blocked
  • 一定是进入了被Synchronized保护的代码
  • 比如线程A进入了一个synchronized方法,线程B也想进入这个方法
  • 但是这个方法的锁已经被线程A获取了,这个时候线程B就处于BLOCKED状态
  • WAITING(无限期等待) Waiting
  • 处于waiting状态的线程会等待另外一个线程处理特殊的行为
  • 举个例子,如果一个线程调用了wait方法(并且没有使用timeout参数),那么这个线程就会处于waiting状态直到另外一个线程调用这个对象的notify或者notifyAll方法后才会解除这个状态
  • 线程调用以下方法会处于无限期等待状态:
  • 1-没有设置Timeout参数的 Object.wait()方法
  • 2-没有设置Timeout参数的 Thread.join()方法
  • 3-LockSupport.park()方法
  • Object.wait(),Thread.join(),LockSupport.park()方法会让线程从Runnable进入Waiting状态
  • 注意这里的方法不带参数,等待没有时间限制
  • 会一直等待,直到手动唤醒
  • 唤醒信号:Object.notify(),Object.notifyAll(),LockSupport.unpark()会让线程从Waiting唤醒,回到Runnable状态
  • TIMED_WAITING(限期等待) Timed Waiting
  • 无需等待其它线程显式地唤醒,在一定时间之后会被系统自动唤醒
  • 等待时间内,也可以被唤醒信号唤醒
  • 线程调用带有正的等待时间参数的下列各方法时,会处于定时等待状态:
  • 1-Thread.sleep(long millis)方法,常常用“使一个线程睡眠”进行描述
  • 2-设置了Timeout参数的 Object.wait()方法,常常用“挂起一个线程”进行描述
  • 3-设置了Timeout参数的 Thread.join()方法
  • 4-LockSupport.parkNanos()方法(带有时间)
  • 5-LockSupport.parkUntil()方法(带有时间)
  • 一般来说,把Blocked(被阻塞)、Waiting(无限期等待)、Timed_Waiting(限期等待)都称为阻塞状态,不仅仅是Blocked
  • 睡眠和挂起是用来描述行为,而阻塞和等待用来描述状态
  • 阻塞和等待的区别在于,阻塞是被动的,它是在等待获取一个排它锁
  • 而等待是主动的,通过调用 Thread.sleep() 和 Object.wait() 等方法进入
  • TERMINATED(终止状态) Terminated
  • 已经执行完毕,已终止线程的线程状态,线程已经结束执行
  • 可以是线程结束任务之后自己结束,或者因产生了异常而结束
  • 上述6种状态在遇到特定事件发生的时候将会互相转换,它们的转换关系如下图:
  • 上图状态的转换和方法已经很清晰了
  • 锁池队列:当资源被一个线程访问时,上锁后,其他线程就会进入锁池队列,当锁释放后,其他线程获得了锁,就会变成可运行状态
  • 《Thinking in Java》中线程被阻塞的五种可能原因:
    1. 线程调用 sleep(ms) ,使线程睡眠,规定时间内,该线程不会运行
    2. 使用suspend()暂停了线程的执行,除非收到resume()消息,否则不会进入可运行状态
    3. 线程正在等待一些IO操作完成
    4. 线程试图调用另一个对象的同步方法,但那个对象处于锁状态,暂时无法使用
    5. 调用wait()暂停了线程的执行,进入了等待队列

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

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

相关文章

HackTheBox_knote

前言 最近打算刷一些内核利用的 CTF 的题目~~~ 题目分析 内核版本:v5.8.3,但是没有开启 cg 隔离smap/smep/kpti/kaslr 全关,可以 ret2usr,所以应该是比较老的题目了(:这里很奇怪的是就算设置 kaslr 但是…

C++入门系列-类和对象(上)

🌈个人主页:羽晨同学 💫个人格言:“成为自己未来的主人~” 面向对象和面向过程初步认识 C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数来逐步解决问题。 C是面向对象的,…

数据仓库实验三:分类规则挖掘实验

目录 一、实验目的二、实验内容和要求三、实验步骤1、创建数据库和表2、决策树分类规则挖掘(1)新建一个 Analysis Services 项目 jueceshu(2)建立数据源视图(3)建立挖掘结构 DST.dmm(4&#xff…

【算法小白周赛2】A.朋友遍天下(easy)C++代码和题解

题目链接:https://www.starrycoding.com/problem/165 题目描述 本题与hard版本有一定区别,仅“拜访时间安排表”的规则相同,hard版本需要进行一定修改才能通过easy版本。 醋酸锌有许多的好友,为了能好好拜访他的每一个好友&…

【C++】文件

目录 文件文件分类文本文件的读写(ASCII文件)的读写打开文件打开文件的方式关闭文件将数据写入ASCII文件从ASCII文件读入数据 二进制存储对比ASCII和二进制存储用成员函数read和write读写二进制文件打开方式文件的读入与读出 文件 所谓文件,一般指存储在外部介质上…

spring框架学习记录(2)

文章目录 注解开发bean相关注解开发定义bean纯注解开发纯注解开发中bean的管理 依赖注入相关依赖注入第三方bean管理第三方bean依赖注入 AOP(Aspect Oriented Programming)面向切面编程AOP简介AOP核心概念AOP工作流程AOP切入点表达式通知类型AOP通知获取数据 注解开发 bean相关…

什么是数据倾斜?怎么解决?——Java全栈知识(12)

什么是数据倾斜?怎么解决? 1、什么是数据倾斜 数据倾斜是指在分布式计算或数据库环境中,数据分布不均匀的现象。在理想的分布式系统中,数据和计算负载应该均匀分布在所有节点上。然而,由于各种原因,某些节…

分库分表都有哪些算法?——Java全栈知识(10)

分库分表都有哪些算法 ? 1、hash 取模 通过分片键进行 hash 取模,取模的数量就是分表的数量。 缺点: 不利于扩容 2、关键词分表 通过创建时间等的关键字来进行分表,例如一个月一张表等。 优点: 方便扩容 缺点&…

wpf线程中更新UI的4种方式

在wpf中,更新UI上面的数据,那是必经之路,搞不好,就是死锁,或者没反应,很多时候,都是嵌套的非常深导致的。但是更新UI的方式,有很多的种,不同的方式,表示的意思…

Leetcode—422. 有效的单词方块【简单】Plus

2024每日刷题&#xff08;126&#xff09; Leetcode—422. 有效的单词方块 实现代码 class Solution { public:bool validWordSquare(vector<string>& words) {int row words.size();for(int i 0; i < row; i) {// 当前这一行的列数int col words[i].length(…

基于Spring Boot的在线BLOG网设计与实现

基于Spring Boot的在线BLOG网设计与实现 开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/idea 系统部分展示 前台首页管理界面&#xff0c;用户经过登录前台首页查看通…

使用docker-compose编排lnmp(dockerfile)完成wordpress

文章目录 使用docker-compose编排lnmp&#xff08;dockerfile&#xff09;完成wordpress1、服务器环境2、Docker、Docker-Compose环境安装2.1 安装Docker环境2.2 安装Docker-Compose 3、nginx3.1 新建目录&#xff0c;上传安装包3.2 编辑Dockerfile脚本3.3 准备nginx.conf配置文…

Vue 组件间的数据绑定

在Vue组件中&#xff0c;v-model指令可以用来实现双向数据绑定。它用于将组件的属性和父组件中的数据进行双向绑定&#xff0c;使得当属性的值改变时&#xff0c;父组件中的数据也会相应地改变&#xff0c;并且当父组件中的数据改变时&#xff0c;属性的值也会相应地改变。 目…

gdb中观察点(watch)如何使用

在GDB中&#xff0c;watch命令用于设置监视点&#xff08;watchpoint&#xff09;&#xff0c;它允许你在程序执行过程中监视特定变量的值何时发生变化。当被监视的变量的值改变时&#xff0c;程序将暂停执行&#xff0c;使你有机会检查变量值的变化和当前的程序状态。这对于调…

C++相关概念和易错语法(9)(变量的存储、new和delete混用分析)

1.变量的存储 当我们运行代码时&#xff0c;相关的变量、函数都暂存在内存的不同区域&#xff0c;接下来我就分析一下易错的几种情况&#xff1a; &#xff08;1&#xff09;局部变量&#xff1a; a.仅static修饰 单独有static修饰&#xff08;无const&#xff09;的变量&a…

Bartender 5 - MacBook菜单栏图标管理软件

当 macOS 桌面图标太多时&#xff0c;既不美观又经常会相互遮盖&#xff0c;非常影响操作。 苹果现在还把「刘海屏」发扬光大&#xff0c;MacBook 的菜单栏是越来越不方便了&#xff01; 如果你希望 Mac 的菜单栏干净清爽、又方便易用&#xff0c;那「Bartender 5」你一定要试…

Rust web简单实战

一、使用async搭建简单的web服务 1、修改cargo.toml文件添加依赖 [dependencies] futures "0.3" tokio { version "1", features ["full"] } [dependencies.async-std] version "1.6" features ["attributes"]2、搭…

Rust 生命周期浅谈

1. 简述 Rust 中的每一个引用都有其 生命周期&#xff08;lifetime&#xff09;&#xff0c;也就是引用保持有效的作用域。大部分时候生命周期是隐含并可以推断的&#xff0c;正如大部分时候类型也是可以推断的一样。类似于当因为有多种可能类型的时候必须注明类型&#xff0c;…

Codeforces Round 943 (Div. 3) G2. Division + LCP (hard version)

题目 思路&#xff1a; #include <bits/stdc.h> using namespace std; //#define int long long 开这个会TLE #define __int128 long long #define pb push_back #define fi first #define se second #define lson p << 1 #define rson p << 1 | 1 const in…

FFmpeg学习记录(二)—— ffmpeg多媒体文件处理

1.日志系统 常用的日志级别&#xff1a; AV_LOG_ERRORAV_LOG_WARNINGAV_LOG_INFOAV_LOG_DEBUG #include <stdio.h> #include <libavutil/log.h>int main(int argc, char *argv[]) {av_log_set_level(AV_LOG_DEBUG);av_log(NULL, AV_LOG_DEBUG, "hello worl…