13.7.深入理解jstack日志,线程的状态

2024-04-19 16:48

本文主要是介绍13.7.深入理解jstack日志,线程的状态,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

13.7.深入理解jstack日志

转自:https://blog.csdn.net/iteye_5603/article/details/82652200

在分析线上问题时常使用到jstack 命令将当时Java应用程序的线程堆栈dump出来。
面对jstack 日志,我们如何查看?

首先要清楚线程的状态
线程的状态有:new、runnable、running、waiting、timed_waiting、blocked、dead
线程状态变迁图:
在这里插入图片描述
各状态说明:
New: 当线程对象创建时存在的状态,此时线程不可能执行;
Runnable:当调用thread.start()后,线程变成为Runnable状态。只要得到CPU,就可以执行;
Running:线程正在执行;
Waiting:执行thread.join()或在锁对象调用obj.wait()等情况就会进该状态,表明线程正处于等待某个资源或条件发生来唤醒自己;
Timed_Waiting:执行Thread.sleep(long)、thread.join(long)或obj.wait(long)等就会进该状态,与Waiting的区别在于Timed_Waiting的等待有时间限制;
Blocked:如果进入同步方法或同步代码块,没有获取到锁,则会进入该状态。
Dead:线程执行完毕,或者抛出了未捕获的异常之后,会进入dead状态,表示该线程结束

其次,对于jstack日志,我们要着重关注如下关键信息
Deadlock:表示有死锁
Waiting on condition:等待某个资源或条件发生来唤醒自己。具体需要结合jstacktrace来分析,比如线程正在sleep,网络读写繁忙而等待
Blocked:阻塞Waiting on monitor entry:在等待获取锁
in Object.wait():获取锁后又执行obj.wait()放弃锁
对于Waiting on monitor entryin Object.wait()的详细描述:Monitor是 Java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者 Class的锁。每一个对象都有,也仅有一个 monitor。从下图中可以看出,每个 Monitor在某个时刻,只能被一个线程拥有,该线程就是 “Active Thread”,而其它线程都是 “Waiting Thread”,分别在两个队列" Entry Set"和"Wait Set"里面等候。在"Entry Set"中等待的线程状态是"Waiting for monitor entry",而在"Wait Set"中等待的线程状态是"in Object.wait()"
在这里插入图片描述
最后通过示例来实践一下
示例一:描述Blocked 和 Waiting to lock
在这里插入图片描述
执行后程序输出:
Thread[main,5,main]
说明主线程先进入同步代码块,获取到thread2对象上的锁。
通过jstack输出结果:
在这里插入图片描述
先说明下日志格式:
"thread2"为线程名称,在平时创建线程或线程池时请务必取一个见明之义的线程名称,方便排查问题
prio=6:线程优先级,不用关心;
tid=0x0000000006540800:线程id,不用关心;
nid=0x2be4:操作系统映射的线程id, 非常关键,后面再使用jstack时补充。
waiting for monitor entry:表示线程正在等待获取锁
0x0000000006dbf000:线程栈起始地址

从jstack日志中,可以看到:主线程获取到thread2对象上的锁,因此正在执行sleep操作,状态为TIMED_WAINTING, 而thread2由于未获取到thread2对象上的锁,因此处于BLOCKED状态。
再细看,thread2 正在"waiting to lock <0x00000000d719d280>“,即试图在地址为0x00000000d719d280所在的对象获取锁,而该锁却被main线程占有(locked <0x00000000d719d280>)。main线程正在"waiting on condition”,说明正在等待某个条件触发,由jstacktrace来看,此线程正在sleep。
经验:如果在jstack日志发现大量的线程在waiting to lock 某个地址,只要能查到哪个线程获取到锁就可以方便定位问题了

示例二:描述waiting on condition
在这里插入图片描述
jstack日志输出结果:
在这里插入图片描述

从日志中可以看到,main线程的状态是Waiting,正在"waiting on condition"来唤醒自己。
结合jstackstrace日志来看,"parking to wait for <0x00000000d719ba70> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)"说明在调用ArrayBlockingQueue.put()阻塞了。

示例三:描述Object.wait()
在这里插入图片描述
程序输出结果:

Thread[thread2,5,main]
Thread[main,5,main]

说明线程thread2先进入同步代码块,获取到thread2对象上的锁。
jstack日志输出结果:
在这里插入图片描述
可以看出:线程thread2的状态是"Waiting", 正在"in Object.wait()"。表明该线程在获取到对象锁后,调用obj.wait()方法,放弃了锁,进入了"Wait Set"队列。

这篇关于13.7.深入理解jstack日志,线程的状态的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/918099

相关文章

Linux线程之线程的创建、属性、回收、退出、取消方式

《Linux线程之线程的创建、属性、回收、退出、取消方式》文章总结了线程管理核心知识:线程号唯一、创建方式、属性设置(如分离状态与栈大小)、回收机制(join/detach)、退出方法(返回/pthr... 目录1. 线程号2. 线程的创建3. 线程属性4. 线程的回收5. 线程的退出6. 线程的取消7.

Linux下进程的CPU配置与线程绑定过程

《Linux下进程的CPU配置与线程绑定过程》本文介绍Linux系统中基于进程和线程的CPU配置方法,通过taskset命令和pthread库调整亲和力,将进程/线程绑定到特定CPU核心以优化资源分配... 目录1 基于进程的CPU配置1.1 对CPU亲和力的配置1.2 绑定进程到指定CPU核上运行2 基于

深入理解Go语言中二维切片的使用

《深入理解Go语言中二维切片的使用》本文深入讲解了Go语言中二维切片的概念与应用,用于表示矩阵、表格等二维数据结构,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录引言二维切片的基本概念定义创建二维切片二维切片的操作访问元素修改元素遍历二维切片二维切片的动态调整追加行动态

Javaee多线程之进程和线程之间的区别和联系(最新整理)

《Javaee多线程之进程和线程之间的区别和联系(最新整理)》进程是资源分配单位,线程是调度执行单位,共享资源更高效,创建线程五种方式:继承Thread、Runnable接口、匿名类、lambda,r... 目录进程和线程进程线程进程和线程的区别创建线程的五种写法继承Thread,重写run实现Runnab

SpringBoot线程池配置使用示例详解

《SpringBoot线程池配置使用示例详解》SpringBoot集成@Async注解,支持线程池参数配置(核心数、队列容量、拒绝策略等)及生命周期管理,结合监控与任务装饰器,提升异步处理效率与系统... 目录一、核心特性二、添加依赖三、参数详解四、配置线程池五、应用实践代码说明拒绝策略(Rejected

C++ Log4cpp跨平台日志库的使用小结

《C++Log4cpp跨平台日志库的使用小结》Log4cpp是c++类库,本文详细介绍了C++日志库log4cpp的使用方法,及设置日志输出格式和优先级,具有一定的参考价值,感兴趣的可以了解一下... 目录一、介绍1. log4cpp的日志方式2.设置日志输出的格式3. 设置日志的输出优先级二、Window

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

解读GC日志中的各项指标用法

《解读GC日志中的各项指标用法》:本文主要介绍GC日志中的各项指标用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、基础 GC 日志格式(以 G1 为例)1. Minor GC 日志2. Full GC 日志二、关键指标解析1. GC 类型与触发原因2. 堆

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操

从原理到实战深入理解Java 断言assert

《从原理到实战深入理解Java断言assert》本文深入解析Java断言机制,涵盖语法、工作原理、启用方式及与异常的区别,推荐用于开发阶段的条件检查与状态验证,并强调生产环境应使用参数验证工具类替代... 目录深入理解 Java 断言(assert):从原理到实战引言:为什么需要断言?一、断言基础1.1 语