今天看到一篇好的文章,转载下。
-------------------------------------------------------------------------------------------------------------------------------------
当遇到问题或者基于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。
相关推荐
项目集成了ATR解析程序和PCSC程序,调用javax.smartcardio连接读卡器,可以发送APDU指令并显示出来。自动解析ATR。实现部分snooper的功能,也带有简约好看的界面。
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® Performance Companion shows how to systematically and proactively improve Java performance with today’s advanced multicore hardware and complex operating system environments. The authors, who...
java源码反码梯度依赖分析 gradle 的依赖分析插件。 这个插件基于 .gist 中的工作。 由于这项工作,这个插件是可能的; 谢谢你。 这个插件试图复制 maven 依赖插件的分析目标的功能,如果依赖被声明但未使用或使用但...
Java® Performance Companion shows how to systematically and proactively improve Java performance with today’s advanced multicore hardware and complex operating system environments. The authors, who...
collection-source-code-analyze(Java集合类源代码分析) 对集合类源代码进行分析主要对增删改查操作的源代码进行分析, 因为这四个操作才是集合中最重要的, 其它的操作示情况进行分析, 分析的流程我采用的是自己仿照...
By Wireshark analyze a ‘ping’ commond Open wireshark select our network In order to analyze ping commond, usually select wlan use filter : icmp(Internet Control Message Protocol), because ICMP...
分析.js analyze.js 是一种分析依赖于 node 或 JavaScript 或任何编译为 JavaScript 的语言的应用程序的工具。 动态分析过程侧重于协议函数调用以及确定模块依赖性和各种运行时特征。 analysis.js 包括: 一个后端,...
Synthesize & Power Analyze
analyze requirements, design and implement solutions while demonstrating good judgment in selecting methods and techniques. S/He will have the opportunity to work with some of the best in the industry...
在VC盘安装analyze6.exe,可解决link问题
《java面试800题(包括java,数据库,前台等,绝对全面)》 Q0027 哪些SQL语句在执行时是自动提交的? 数据定义语言DDL是自动提交的。 Q0028 索引对数据库的影响? 提高查询速度 Q0029 主外键有什么关系? 外键是从...
该项目旨在提供一种简单的方法来分析结果。 Caliper 包含一个托管在 Google AppEngine 上的网络界面,但目前它非常缓慢且不可靠:许多结果上传失败。 另外,并不是所有的微基准测试结果都值得分享和放到网上。 有些...
我找了很多资料,终于被我找到了关于Analyze format的一种存储格式。这种格式用于MRI 图像存储~
软件工程课件:第5章 分析设计Analyze & Design.ppt
分析Java代码示例 使用JavaParser从Java源文件中提取信息的一些代码示例 阅读本文中的说明: :
前端开源库-analyze-css分析CSS、CSS选择器的复杂性和性能分析器
前端开源库-analyze-deps分析deps,将package.json中的依赖项与最新的可用版本进行比较。
02GB_Analyze统计分析.pptx
java_collection_source_code_analyze:Java集合部分源码分析