JVM线程分析详解
java线程状态:

- 初始(NEW):新创建了一个线程对象,但还没有调用start()方法。
- 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。
线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。 - 阻塞(BLOCKED):表示线程阻塞于锁。
- 等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
- 超时等待(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回。
- 终止(TERMINATED):表示该线程已经执行完毕。
Java Monitor原理:
Monitor 是Java中用以实现线程之间的互斥与协作的主要手段,可以看成是对象或者Class的锁。每一个对象有且仅有一个monitor。Java 的 Object 类本身就是监视者对象,Java 对于 Monitor Object 模式做了内建的支持。
Object 类本身就是监视者对象!
每个 Object 都带了一把看不见的锁,通常叫 内部锁/Monitor 锁/Instrinsic Lock, 这把锁就是 监控锁。
synchronized 关键字修饰方法和代码块就是 同步方法
wait()/notify()/notifyAll() 方法构成监控条件(Monitor Condition)

线程和Monitor之间关系:
一个Monitor在某个时刻,只能被一个线程拥有,该线程就是Active Thread,
而其它线程都是Waiting Thread,分别在两个队列Entry Set和Wait Set里面等候。
在Entry Set中等待的线程状态是Waiting for monitor entry,
在Wait Set中等待的线程状态是in Object.wait()。
线程进入同步方法中:
为了继续执行临界区代码,线程必须获取 Monitor 锁。如果获取锁成功,将成为该监视者对象的拥有者。任一时刻内,监视者对象只属于一个活动线程(The Owner)
拥有监视者对象的线程可以调用 wait() 进入等待集合(Wait Set),同时释放监视锁,进入等待状态。
其他线程调用 notify() / notifyAll() 接口唤醒等待集合中的线程,这些等待的线程需要重新获取监视锁后才能执行 wait() 之后的代码。
同步方法执行完毕了,线程退出临界区,并释放监视锁。
进入区(Entrt Set):表示线程通过synchronized要求获取对象的锁。如果对象未被锁住,则迚入拥有者;否则则在进入区等待。一旦对象锁被其他线程释放,立即参与竞争。
拥有者(The Owner):表示某一线程成功竞争到对象锁。
等待区(Wait Set):表示线程通过对象的wait方法,释放对象的锁,并在等待区等待被唤醒。
线程调用修饰:
表示线程在方法调用时,额外的重要的操作,一般出现在线程内容中,用来协助分析线程的状态。
locked <对象地址> 对象名: 表示当前线程通过synchronized关键字成功获取到了目标对象的监视器,拥有了在临界区操作的权限,状态一般为runnable。注意对象锁是可重入的,所以这里有2次锁住了同一个对象。
waiting to lock <对象地址> 对象名:
表示当前线程未能通过synchronized关键字获取到目标对象的监视器,状态一般为blocked。
waiting on<对象地址> 对象名:
表示当前线程通过synchronized关键字成功获取到了目标对象的监视器,但调用了wait方法,进入对象的等待区等待。在调用栈顶出现,线程状态为WAITING或TIMED_WATING。
parking to wait for <对象地址> 对象名:
park是基本的线程阻塞原语,不通过监视器在对象上阻塞。随concurrent包会出现的新的机制,与synchronized体系不同,具体介绍可以看stackoverflow上的回答传送门。
系统线程状态:
出现在线程信息第一行的末尾。
deadlock:死锁线程
runnable:表示线程运行中或I/O等待,线程状态一般为RUNNABLE。
in Object.wait():进入临界区之后,又调用了java.lang.Object.wait()方法等待,jvm线程状态一般为WAITING或TIMED_WAITING。
waiting for monitor entry:在等待进入一个临界区,线程状态一般状态为BLOCKED。
waiting on condition:线程正处于等待资源或等待某个条件的发生,具体的原因需要结合下面堆栈信息进行分析。
(1)如果堆栈信息明确是应用代码,则证明该线程正在等待资源,一般是大量读取某种资源且该资源采用了资源锁的情况下,线程进入等待状态,等待资源的读取,或者正在等待其他线程的执行等。
(2)如果发现有大量的线程都正处于这种状态,并且堆栈信息中得知正等待网络读写,这是可能因为网络阻塞导致线程无法执行。
(3)还有一种常见的情况是该线程在sleep,等待sleep的时间到了,将被唤醒。
JVM线程状态:
java.lang.Thread.State: RUNNABLE 线程运行中或I/O等待 方法调用-无
java.lang.Thread.State: BLOCKED (on object monitor) 等待进入一个临界区 方法调用-synchronized
java.lang.Thread.State: TIMED_WAITING (parking) 线程等待唤醒,并且设置等待时长 方法调用-LockSupport.parkNanos(等待时长)、LockSupport.parkUntil(等待时长)
java.lang.Thread.State: TIMED_WAITING (sleeping) 线程等待唤醒,并且设置等待时长 方法调用-Thread.sleep(等待时长),Thread.join(等待时长)
java.lang.Thread.State: TIMED_WAITING (on object monitor) 线程在等待唤醒,并且设置等待时长 方法调用-Object.wait(等待时长)
java.lang.Thread.State: WAITING (parking) 线程等待唤醒,没有设置等待时长 方法调用-LockSupport.park()
java.lang.Thread.State: WAITING (on object monitor) 线程等待唤醒,并且没有设置等待时长 方法调用-Object.wait()
java.lang.Thread.State: WAITING (on object monitor) 线程等待唤醒,没有设置等待时长 方法调用-Thread.join()
jvm日志分析:
“ForkJoinPool.commonPool-worker-52”{线程名} #5688{线程ID} daemon prio=5{线程的优先级,取值范围为[1-10],默认为 5,数值越低越有优先} os_prio=0{线程在操作系统中的优先级} tid=0x00007f31eb3f3800 nid=0xa8ec{Native thread ID,本地操作系统相关的线程id,对应JVM 虚拟机中线程映射在操作系统中的线程编号。(这个nid就是我们用top -Hp pid 查看到的线程号,不过要用printf "%x\n"转换一下进制)} waiting on condition [0x00007f31944d0000]{系统线程状态}
java.lang.Thread.State: WAITING (parking){JVM线程状态}
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000004706e6598> (a java.util.concurrent.ForkJoinPool)
at java.util.concurrent.ForkJoinPool.awaitWork(ForkJoinPool.java:1824)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1693)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Locked ownable synchronizers:
- None
常见问题:
1)锁争用
如果出现大量的锁争用,可能是线程阻塞了!
#48线程获得了 <0x000000046b9b6078>对象的锁,进入了临界区;#49无法获取到锁,停留在Entry Set中,输出waiting to lock <0x000000046b9b6078>。
“hiveserver2-web-49-acceptor-2@23302924-ServerConnector@6d6d480c{HTTP/1.1,[http/1.1]}{0.0.0.0:10002}” #49 daemon prio=3 os_prio=0 tid=0x00007f31eaf33000 nid=0x6306 waiting for monitor entry [0x00007f31a3dfc000]
java.lang.Thread.State: BLOCKED (on object monitor) --JVM线程状态
at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:234)
- waiting to lock <0x000000046b9b6078> (a java.lang.Object)
at org.eclipse.jetty.server.ServerConnector.accept(ServerConnector.java:397)
at org.eclipse.jetty.server.AbstractConnector$Acceptor.run(AbstractConnector.java:601)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
“hiveserver2-web-48-acceptor-1@580fe4f0-ServerConnector@6d6d480c{HTTP/1.1,[http/1.1]}{0.0.0.0:10002}” #48 daemon prio=3 os_prio=0 tid=0x00007f31eaf31800 nid=0x6305 runnable [0x00007f31a3efd000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)
at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:422)
at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:250)
- locked <0x000000046b9b6078> (a java.lang.Object)
at org.eclipse.jetty.server.ServerConnector.accept(ServerConnector.java:397)
at org.eclipse.jetty.server.AbstractConnector$Acceptor.run(AbstractConnector.java:601)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
2)死锁
如果两个线程相互都被对方的线程锁锁住,这样就造成了死锁。
Thread1获取了<0x00000000d8251168>锁,等待<0x00000000d8251198>锁;Thread2获取了<0x00000000d8251198>锁,等待<0x00000000d8251168>锁。导致死锁!
“Thread2” daemon prio=5 tid=0x00007f1d3825f800 nid=0x2142 waiting for monitor entry [0x00007f1d16eeb000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.jvm.study.threaddump.deadlock.DeadLockMock$2.run(DeadLockMock.java:31)
- waiting to lock <0x00000000d8251168> (a java.lang.String)
- locked <0x00000000d8251198> (a java.lang.String)
“Thread1” daemon prio=5 tid=0x00007f1d3825e000 nid=0x2141 waiting for monitor entry [0x00007f1d16fec000]
ava.lang.Thread.State: BLOCKED (on object monitor)
at com.jvm.study.threaddump.deadlock.DeadLockMock$1.run(DeadLockMock.java:16)
- waiting to lock <0x00000000d8251198> (a java.lang.String)
- locked <0x00000000d8251168> (a java.lang.String)
3)等待区等待
JVM线程的状态是java.lang.Thread.State: TIMED_WAITING (on object monitor),线程调用了java.lang.Object.wait(Native Method)方法而进入了等待状态。
"Wait Set"中等待的线程状态就是 in Object.wait();
当线程获得了Monitor进入临界区之后,如果发现线程继续运行的条件没有满足,它就调用对象(通常是被synchronized的对象)的wait()方法,放弃了Monitor,进入"Wait Set"队列中。
只有当别的线程在该对象上调用了notify()或notifyAll()方法, “Wait Set” 队列中线程才得到机会去竞争,但是只有一个线程获得对象的 Monitor,从而恢复到运行态。
“IPC Client (2108708444) connection to IT-CDH-Node02/10.11.16.36:8020 from hive” #5681 daemon prio=5 os_prio=0 tid=0x00007f31ccf4a000 nid=0xa8e4 in Object.wait() [0x00007f319aa33000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at org.apache.hadoop.ipc.ClientConnection.waitForWork(Client.java:1017)
- locked <0x000000042b52dbf0> (a org.apache.hadoop.ipc.Client$Connection)
at org.apache.hadoop.ipc.ClientConnection.run(Client.java:1061)
Locked ownable synchronizers:
- None
相关文章:
JVM线程分析详解
java线程状态: 初始(NEW):新创建了一个线程对象,但还没有调用start()方法。运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。 线程对象创建…...
毕业项目推荐:基于yolov8/yolo11的野生菌菇检测识别系统(python+卷积神经网络)
文章目录 概要一、整体资源介绍技术要点功能展示:功能1 支持单张图片识别功能2 支持遍历文件夹识别功能3 支持识别视频文件功能4 支持摄像头识别功能5 支持结果文件导出(xls格式)功能6 支持切换检测到的目标查看 二、数据集三、算法介绍1. YO…...
DeepSeek 助力 Vue3 开发:打造丝滑的页眉(Header)
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 Deep…...
常用空间数据结构对比
空间数据结构是用来组织和查询多维空间数据的算法结构。它们在地理信息系统 (GIS)、计算机图形学、机器人导航、机器学习等领域非常重要。以下是几种常见空间数据结构的对比: 1. 四叉树(Quadtree) 适用场景:二维空间数据&#x…...
PHP应用程序设计:一个实际的例子(3)
使应用程序适用于网络 如果你正好计划用P H P开发你自己的服务程序(或者其他一些相似的东西),请重新思考一下。你可能已经对这些思想有些迷惑了:实现一个聊天服务程序意味着实现一个网络服务程序。这是我们实际上介绍给大家的东西…...
RabbitMQ 的介绍与使用
一. 简介 1> 什么是MQ 消息队列(Message Queue,简称MQ),从字面意思上看,本质是个队列,FIFO先入先出,只不过队列中存放的内容是message而已。 其主要用途:不同进程Process/线程T…...
spring boot 连接FTP实现文件上传
spring boot 连接FTP实现文件上传 maven: <!--ftp--><dependency><groupId>commons-net</groupId><artifactId>commons-net</artifactId><version>3.8.0</version></dependency>接口示例: ApiO…...
OpenCV给图像添加噪声
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 如果你已经有了一张干净的图像,并希望通过编程方式向其添加噪声,可以使用 OpenCV 来实现这一点。以下是一个简单的例子&a…...
Elasticsearch:使用阿里云 AI 服务进行嵌入和重新排名
作者:来自 Elastic Toms Mura 将阿里云 AI 服务功能与 Elastic 结合使用。 更多阅读,请参阅 “Elasticsearch:使用阿里 infererence API 及 semantic text 进行向量搜索”。 在本文中,我们将介绍如何将阿里云 AI 功能与 Elastics…...
管理后台环境配置
后端配置及启动 a. 软件安装 1. Java sdk 1.8 2. maven 3.6 3. intellij IDEA 2024 4. Visual C Redistributable 5. mongodb 7.0 6. mysql 8.0 双击安装:mysql-installer-community-8.0.41.0.msi 版本选择:Full,包括服务器和客户端 …...
数字IC低功耗后端设计实现之power gating和isolation技术
考虑低功耗设计需求,下图中间那个功能模块是需要做power domain的,即这个模块需要插MTCMOS。需要开启时,外面的VDD会和这个模块的LOCAL VDD形成通路,否则就是断开即power off状态。 这些低功耗设计实现经验,你真的懂了…...
【网络编程】几个常用命令:ping / netstat / xargs / pidof / watch
ping:检测网络联通 1. ping 的基本功能2. ping 的工作原理3. ping 的常见用法4. ping 的输出解释5. ping 的应用场景6. 注意事项 netstat:查看网络状态 1. netstat 的基本功能2. 常见用法3. 示例4. 输出字段解释5. netstat 的替代工具6. 注意事项 xargs&…...
sqlilab 46 关(布尔、时间盲注)
sqlilabs 46关(布尔、时间盲注) 46关有变化了,需要我们输入sort,那我们就从sort1开始 递增测试: 发现测试到sort4就出现报错: 我们查看源码: 从图中可看出:用户输入的sort值被用于查…...
视觉应用工程师(面试)
视觉应用工程师(面试) 1.自我介绍、会的技能、项目 2.相机和机械手调试过程 检查硬件,看软件驱动是否链接,调节相机和镜头保证能够识别这个物料,看接口和通讯是否正常,如:波特率,数…...
redis restore 命令的用法
Redis 的 RESTORE 命令用于将序列化后的数据(通常由 DUMP 命令生成)恢复为 Redis 的键值。它在数据迁移、备份恢复和跨实例同步等场景中非常有用。以下是详细说明: 作用 数据恢复 将 DUMP 命令生成的序列化数据重新加载到 Redis 中ÿ…...
当AI重构认知:技术狂潮下的教育沉思录
备注:文章未Deepseek R1模型辅助生成,如有不妥请谅解。 以下使原文: 我有三个娃,各间隔4到5岁,经历过搜索引擎,短视频,短剧,本身曾经也是教育专业出生,任何事务都有两面性…...
《Effective Objective-C》阅读笔记(下)
目录 内存管理 理解引用计数 引用计数工作原理 自动释放池 保留环 以ARC简化引用计数 使用ARC时必须遵循的方法命名规则 变量的内存管理语义 ARC如何清理实例变量 在dealloc方法中只释放引用并解除监听 编写“异常安全代码”时留意内存管理问题 以弱引用避免保留环 …...
穷举vs暴搜vs深搜vs回溯vs剪枝(典型算法思想)—— OJ例题算法解析思路
回溯算法的模版 void backtrack(vector<int>& path, vector<int>& choice, ...) {// 满⾜结束条件if (/* 满⾜结束条件 */) {// 将路径添加到结果集中res.push_back(path);return;}// 遍历所有选择for (int i 0; i < choices.size(); i) {// 做出选择…...
【Java项目】基于Spring Boot的校园博客系统
【Java项目】基于Spring Boot的校园博客系统 技术简介:采用Java技术、Spring Boot框架、MySQL数据库等实现。 系统简介:校园博客系统是一个典型的管理系统,主要功能包括管理员:首页、个人中心、博主管理、文章分类管理、文章信息…...
计算机毕业设计SpringBoot+Vue.js图书进销存管理系统(源码+文档+PPT+讲解)
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...
算法-数据结构(图)-迪杰斯特拉最短逻辑算法( Dijkstra)
迪杰斯特拉算法(Dijkstras Algorithm) 是一种用于计算单源最短路径的经典算法,由荷兰计算机科学家 艾兹赫尔迪杰斯特拉(Edsger W. Dijkstra) 于1956年提出。它的主要目标是找到从图中的某个源节点到所有其他节点的最短…...
C语言【进阶篇】之指针——涵盖基础、数组与高级概念
目录 🚀前言🤔指针是什么🌟指针基础💯内存与地址💯指针变量💯 指针类型💯const 修饰指针💯指针运算💯野指针和 assert 断言 💻数组与指针💯数组名…...
关于命令行下的 git( git add、git commit、git push)
文章目录 关于 gitgit 的概念git 操作(git add、git commit、git push 三板斧)安装 git新建仓库及配置git clone.gitignoregit addgit commitgit push其他 git 指令git pull(把远端的东西拉到本地进行同步)其他指令 关于 git git…...
DaoCloud 亮相 2025 GDC丨开源赋能 AI 更多可能
2025 年 2 月 21 日至 23 日,上海徐汇西岸,2025 全球开发者先锋大会以 “模塑全球,无限可能” 的主题,围绕云计算、机器人、元宇宙等多元领域,探讨前沿技术创新、应用场景拓展和产业生态赋能,各类专业论坛、…...
极速探索 HarmonyOS NEXT:开启国产操作系统开发的新篇章
极速探索 HarmonyOS NEXT:开启国产操作系统开发的新篇章 一、引言二、HarmonyOS NEXT 是什么?背景核心特性 三、HarmonyOS NEXT 的发展历程从 LiteOS 到 HarmonyOS 的逐步演进HarmonyOS NEXT 5.0 的发布 四、HarmonyOS NEXT 对科技的影响技术突破开发者生…...
火狐浏览器多开指南:独立窗口独立IP教程
无论是跨境电商从业者需要管理多个店铺账号,还是海外社交媒体营销人员要运营多个社交平台账号,亦或是从事多账号广告投放的人员,都面临着一个共同的挑战 —— 如何高效管理多个账号,并确保每个账号的独立性。 在这种情况下&#…...
内容中台是什么?内容管理平台解析
内容中台的核心价值 现代企业数字化转型进程中,内容中台作为中枢系统,通过构建统一化的内容管理平台实现数据资产的高效整合与智能调度。其核心价值体现在打破传统信息孤岛,将分散于CRM、ERP等系统的文档、知识库、产品资料进行标准化归集&a…...
1.2 Kaggle大白话:Eedi竞赛Transformer框架解决方案02-GPT_4o生成训练集缺失数据
目录 0. 本栏目竞赛汇总表1. 本文主旨2. AI工程架构3. 数据预处理模块3.1 配置数据路径和处理参数3.2 配置API参数3.3 配置输出路径 4. AI并行处理模块4.1 定义LLM客户端类4.2 定义数据处理函数4.3 定义JSON保存函数4.4 定义数据分片函数4.5 定义分片处理函数4.5 定义文件名排序…...
iOS指纹归因详解
iOS 指纹归因(Fingerprint Attribution)详解 1. 指纹归因的概念 指纹归因(Fingerprint Attribution)是一种无 ID 归因(ID-less Attribution)技术,主要用于广告跟踪、用户识别或流量分析。它基…...
sql server笔记
创建数据库 use master gocreate database stuuuuu//删除数据库if db_id ($$$) is not nullDrop database [$$$] go//新建表USE [studyTest] GOSET ANSI_NULLS ON GOSET QUOTED_IDENTIFIER ON GOCREATE TABLE [dbo].[Table_1]([id] [int] NULL,[name] [varchar](10) NULL ) ON…...
