今天看到一篇好的文章,转载下。
-------------------------------------------------------------------------------------------------------------------------------------
当遇到问题或者基于java web的程序跑的比期望中慢,这时候我们需要使用线程dump。如果thread dump对你感觉比较复杂,这篇文章将会帮助你。这里我将先简单介绍一下java线程中的一些简单概念等,然后如何从一个正在跑的程序里面dump thread,之后分析这些线程的各个状态,然后优化性能。
web类服务使用数以百计的线程来处理大量用户的并发请求。如果两个或者更多的线程需要使用相同的资源,这时候就不可避免的出现线程间的竞争或者死锁现象。
线程竞争是指一个线程等待被另外一个线程占用的锁,例如在web应用中,不同的线程要获取共享资源。
线程死锁是指两个或多线线程互相等待对方完成任务,进入了无限的等待中。
为了分析线程的dump信息,需要了解线程的各个状态,下面这张图形象的介绍了几种状态。
NEW: 线程被创建,但是没有被执行
RUNNABLE: 线程获取到了CPU的分片,处理任务(有可能处于WAITING状态,这取决于操作系统)
BLOCKED:线程等带其他线程释放锁
WAITING:程序调用wait/join方法,使线程处于等待状态
TIMED_WAITING: 线程等待特定的时间,程序调用sleep、wait、join,并带有时间参数
(一)获取线程的dump信息
(1)通过使用JDK自带的jstack获取线程dump信息;
(2)通过可视化工具,例如jconsole、visoleVM来获取
通过可视化工具非常简单,这里不做介绍,线上环境还是用命令行的形式搞定。
1、获取进程的PID,(jps or ps –ef | grep jva or pgrep java)
2、jstack 打印文件,可以重定向到一个文件保存起来
Jstack中的参数:
-F 强制进行线程dump,当执行jstack pid没有反应的时候,可以执行此命令
-m 打印java线程还有本地线程
-l 打印线程的锁附加信息
(二)线程信息中各个字段的含义
"pool-1-thread-13" prio=6 tid=0x000000000729a000 nid=0x2fb4 runnable [0x0000000007f0f000] java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
Thread name: When using Java.lang.Thread class to generate a thread, the thread will be named Thread-(Number), whereas when using java.util.concurrent.ThreadFactory class, it will be named pool-(number)-thread-(number).
Priority: 代表线程的优先级
Thread ID: 线程的唯一标示,通过这个ID可以获取一些有用的信息,例如CPU以及内存使用情况
Thread status: 线程的状态
Thread callstack: 方法栈中的信息
线程处于BLOCKED状态
例如下面的信息,线程在等待锁。
"BLOCKED_TEST pool-1-thread-2" prio=6 tid=0x0000000007673800 nid=0x260c waiting for monitor entry [0x0000000008abf000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.nbp.theplatform.threaddump.ThreadBlockedState.monitorLock(ThreadBlockedState.java:43)
- waiting to lock <0x0000000780a000b0> (a com.nbp.theplatform.threaddump.ThreadBlockedState)
at com.nbp.theplatform.threaddump.ThreadBlockedState$2.run(ThreadBlockedState.java:26)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Locked ownable synchronizers:
- <0x0000000780b0c6a0> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
"
(三)死锁的情况
线程A需要获取线程B的锁才能完成它的任务,同时线程B需要获取线程A的锁来进行任务。
例如下面的信息中,
线程 DEADLOCK_TEST-1 thread 有 0x00000007d58f5e48 这个锁,试图获取这个锁 0x00000007d58f5e60 .
线程 DEADLOCK_TEST-2 thread 有0x00000007d58f5e60 这个锁,试图获取这个锁 0x00000007d58f5e78 .
线程DEADLOCK_TEST-3 thread 有 0x00000007d58f5e78 这个锁,试图获取这个锁 0x00000007d58f5e48 l
从而导致死锁。
"DEADLOCK_TEST-1" daemon prio=6 tid=0x000000000690f800 nid=0x1820 waiting for monitor entry [0x000000000805f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.nbp.theplatform.threaddump.ThreadDeadLockState$DeadlockThread.goMonitorDeadlock(ThreadDeadLockState.java:197)
- waiting to lock <0x00000007d58f5e60> (a com.nbp.theplatform.threaddump.ThreadDeadLockState$Monitor)
at com.nbp.theplatform.threaddump.ThreadDeadLockState$DeadlockThread.monitorOurLock(ThreadDeadLockState.java:182)
- locked <0x00000007d58f5e48> (a com.nbp.theplatform.threaddump.ThreadDeadLockState$Monitor)
at com.nbp.theplatform.threaddump.ThreadDeadLockState$DeadlockThread.run(ThreadDeadLockState.java:135)
Locked ownable synchronizers:
- None
"DEADLOCK_TEST-2" daemon prio=6 tid=0x0000000006858800 nid=0x17b8 waiting for monitor entry [0x000000000815f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.nbp.theplatform.threaddump.ThreadDeadLockState$DeadlockThread.goMonitorDeadlock(ThreadDeadLockState.java:197)
- waiting to lock <0x00000007d58f5e78> (a com.nbp.theplatform.threaddump.ThreadDeadLockState$Monitor)
at com.nbp.theplatform.threaddump.ThreadDeadLockState$DeadlockThread.monitorOurLock(ThreadDeadLockState.java:182)
- locked <0x00000007d58f5e60> (a com.nbp.theplatform.threaddump.ThreadDeadLockState$Monitor)
at com.nbp.theplatform.threaddump.ThreadDeadLockState$DeadlockThread.run(ThreadDeadLockState.java:135)
Locked ownable synchronizers:
- None
"DEADLOCK_TEST-3" daemon prio=6 tid=0x0000000006859000 nid=0x25dc waiting for monitor entry [0x000000000825f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.nbp.theplatform.threaddump.ThreadDeadLockState$DeadlockThread.goMonitorDeadlock(ThreadDeadLockState.java:197)
- waiting to lock <0x00000007d58f5e48> (a com.nbp.theplatform.threaddump.ThreadDeadLockState$Monitor)
at com.nbp.theplatform.threaddump.ThreadDeadLockState$DeadlockThread.monitorOurLock(ThreadDeadLockState.java:182)
- locked <0x00000007d58f5e78> (a com.nbp.theplatform.threaddump.ThreadDeadLockState$Monitor)
at com.nbp.theplatform.threaddump.ThreadDeadLockState$DeadlockThread.run(ThreadDeadLockState.java:135)
Locked ownable synchronizers:
- None
(四)程序反常的比较慢时,如何来处理?
在多次dump之后,发现有以下几个线程处于阻塞状态
" DB-Processor-13" daemon prio=5 tid=0x003edf98 nid=0xca waiting for monitor entry [0x000000000825f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at beans.ConnectionPool.getConnection(ConnectionPool.java:102)
- waiting to lock <0xe0375410> (a beans.ConnectionPool)
at beans.cus.ServiceCnt.getTodayCount(ServiceCnt.java:111)
at beans.cus.ServiceCnt.insertCount(ServiceCnt.java:43)
"DB-Processor-14" daemon prio=5 tid=0x003edf98 nid=0xca waiting for monitor entry [0x000000000825f020]
java.lang.Thread.State: BLOCKED (on object monitor)
at beans.ConnectionPool.getConnection(ConnectionPool.java:102)
- waiting to lock <0xe0375410> (a beans.ConnectionPool)
at beans.cus.ServiceCnt.getTodayCount(ServiceCnt.java:111)
at beans.cus.ServiceCnt.insertCount(ServiceCnt.java:43)
" DB-Processor-3" daemon prio=5 tid=0x00928248 nid=0x8b waiting for monitor entry [0x000000000825d080]
java.lang.Thread.State: RUNNABLE
at oracle.jdbc.driver.OracleConnection.isClosed(OracleConnection.java:570)
- waiting to lock <0xe03ba2e0> (a oracle.jdbc.driver.OracleConnection)
at beans.ConnectionPool.getConnection(ConnectionPool.java:112)
- locked <0xe0386580> (a java.util.Vector)
- locked <0xe0375410> (a beans.ConnectionPool)
at beans.cus.Cue_1700c.GetNationList(Cue_1700c.java:66)
at org.apache.jsp.cue_1700c_jsp._jspService(cue_1700c_jsp.java:120)
从上面的信息中可以看出,线程阻塞在获取数据库连接,这时候分析可能有两个原因:
第一个是错误的配置;
第二个是反常的数据库连接;
(五)为了方便排查问题,编写多线程代码的时候,最好对线程进行命名
(六)通过使用Mbean获取更多的线程信息
核心的代码如下:
ThreadMXBean mxBean = ManagementFactory.getThreadMXBean();
long[] threadIds = mxBean.getAllThreadIds();
ThreadInfo[] threadInfos =mxBean.getThreadInfo(threadIds);
(七)处理CPU利用率突然特别高的问题,看看CPU最高的那个线程在做什么
例子:查看特定java线程的情况:
(一)通过top命令,查看消耗内存较高的线程的id,
运行top,shift+h来显示所有进程的信息,包含进程中线程的情况,从中找出占用内存最大的那个java线程。
也可直接运行:top -H -p pid 来显示java进程中的各个线程的情况(p是显示特定的进程号,H是显示进程中的所有线程)
(二)进制间的转换:
printf '0x%x\n' pid
获取线程ID的另外一中展现形式
(三)dump线程,然后搜搜索线程为上述ID的线程的信息
总结:
对于这篇文章,我主要对于开发者介绍了一些关于多线程处理的经验,这些对于一些经验丰富的开发者来说可能是一些简单的知识。我感觉对于线程没有提供丰富的背景信息,而是直接介绍了thread dump,我希望这篇文章能够给更多的开发者带来帮助。
转载于:http://iamzhongyong.iteye.com/blog/1441285。
相关推荐
IBM Thread and Monitor Dump Analyzer for Java(简称 jca)。它可以识别Java线程中的挂起,死锁,资源竞争,和瓶颈。 使用方法: java -Xmx1000m -jar jca456.jar
IBM提供的分析javacore和dump的内存分析工具,非常...分析线程情况 JavaCore 或 ThreadDump文件,即线程的映像,用来分析线程资源锁等情况, 可参考:https://blog.csdn.net/weixin_34129696/article/details/85868951
它可能会包含多个方法,如`analyze()`用于执行语法分析,`generateAST()`用于生成抽象语法树,以及可能的错误处理机制。 总的来说,构建一个Java实现的语法分析器涉及到对编译原理的深入理解,包括词法分析、语法...
需要本地安装JDK并配置JAVA环境变量。 之后使用java -jar jca469.jar即可打开工具。 直接将dump出来的堆栈信息,打开,便可分析。
IBM JVM 分析工具,JCA,javaCore查看工具
Java线程转储分析器这是用Java编写的Java线程转储分析器。 执照Java Thread Dump Analyzer是根据,版权属于Spotify AB。本地测试npm installnpm test 使用npm 6.13.7和node v13.8.0测试。去做在“同步器”部分中,使...
"Analyze.java"很可能就是这个词法分析器的核心代码。在这个文件中,开发者可能定义了一些类和方法来实现以下功能: 1. **字符流读取**:词法分析器首先需要读取源代码的字符流,这通常通过Java的`BufferedReader`...
在Java代码中,这部分逻辑可能包含在`BianYi`类的某个方法中,例如`run()`或`analyze()`,但具体实现并未给出。 完成这个实验,需要熟悉正则表达式、状态转换图的概念,以及如何在Java中实现词法分析器。理解并实现...
- `analyze()`: 主要的分析逻辑,根据LR(1)分析表对输入字符串进行分析。 #### 六、扩展与优化建议 1. **动态生成分析表**: 当前项目中的分析表是手动定义的,可以考虑实现一个工具来根据文法规则自动生成分析表...
java hprof(文件类型分析器)是一款功能强大的java问题解析软件。可以帮助大家在编辑过程种遇到问题的话就马上解决哦。有兴趣的话赶紧下载! 软件介绍: 许多配置属性可以控制分析过程,这些属性也可以通过JobConf...
这个类可能会包含一个方法,例如`analyze()`,用于读取源代码并逐字符地进行分析。它会根据预定义的规则判断当前字符或字符组合是否符合某种关键字、标识符、常量、运算符或分隔符的标准。 `GetLetter.java`可能是...
本工具实现了部分Snooper功能,意味着用户可以追踪智能卡操作的全过程,便于分析和学习。 6. **用户界面**:工具还提供了简约美观的图形用户界面(GUI),使得操作更加直观和便捷。用户可以通过界面选择读卡器、...
此外,Java的多线程能力使其在处理大规模计算时具有优势。 5. **Java代码示例** 使用Jython集成Python库进行灵敏度分析: ```java import org.python.util.PythonInterpreter; import org.python.core.*; // ...
Java,Java内存管理,Java 8和Java 9中的多线程和并行计算 Java内存管理 - How to analyze memoty 1. jvisualvm command on mac 2. Eclipse MAT (Memory Analyzer Tool) - Get heap dump, may be from ...
### Java的词法分析器(编译原理实验) #### 概述 本实验基于Java语言实现了一个词法分析器,其主要目的是将源代码转换为一系列的标记(Token)供后续的语法分析等阶段使用。词法分析器是编译器的重要组成部分之一,...
"Analyze_Oracle_Table.rar"这个压缩包文件的主题聚焦于Oracle表的分析,目的是提升查询和执行操作的效率。Oracle的性能可能会因为各种因素而下降,例如索引未被有效利用、数据分布不均匀或者统计信息过时等。因此,...
总的来说,"analyze-java-code-examples"项目为学习和实践JavaParser提供了一个丰富的资源库,帮助开发者深入理解Java代码的内部结构,并能有效地进行分析和修改,提升代码质量和维护性。无论是为了个人项目还是企业...
《analyze-css:深入理解前端CSS分析与优化》 在当今的Web开发中,前端性能是决定用户体验的关键因素之一,而CSS作为构建网页样式的核心技术,其优化显得尤为重要。"analyze-css"是一个强大的开源库,专为前端...
QGroundControl Analyze模块是地面控制站软件QGroundControl的核心组件之一,它专注于处理和分析来自无人机的传感器原始数据。这个模块的源码对于深入理解无人机系统的运行机制、优化飞行性能以及进行定制化开发具有...