- 浏览: 809015 次
- 性别:
- 来自: 杭州
-
文章分类
最新评论
-
huan19900606:
像haskell这些脚本语言很容易定义DSL,实现对应的词法语 ...
DSL的基本介绍(groovy来进行构建) -
express_wind:
https://yq.aliyun.com/album/130 ...
qlexpress规则引擎初探 -
readxuxuegang:
博主你好。如果groovy的代码是保存在数据库里,不是文件,这 ...
在java中使用groovy怎么搞 (java and groovy) -
express_wind:
hi,兄弟,有没有兴趣来阿里巴巴专门做这方面的研究,https ...
qlexpress规则引擎初探 -
langcaiye:
有2个问题请教:1. 这里的base32算法为什么需要以负数的 ...
【原】geohash算法详解
看见一篇比较不错的关于java线程的文章,决定翻译一下,顺便体会一下翻译外文是啥感觉。
原文链接如下呵呵。
http://www.cubrid.org/blog/dev-platform/how-to-analyze-java-thread-dumps/
当遇到问题或者基于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,我希望这篇文章能够给更多的开发者带来帮助。
发表评论
-
系统分布式情况下最终一致性方案梳理
2015-09-05 19:34 40990前言 目前的应用系 ... -
Storm核心概念剖析
2015-03-20 20:42 3242最近团队中有分析的场 ... -
池和流的两种数据处理方式
2014-11-19 22:59 1420在抽象层面,想了一下,目前很多的数据处理形式,一般分为池和流 ... -
关于CodeReview(java)
2014-10-29 20:42 1926关于codereview,在平时的开发中,经常忽略的环节,参 ... -
java中各种各样的数据结构
2014-07-13 20:26 2514在java中,有非常丰富的数据结构,可能是因为大多数的软件 ... -
关于JVM的ClassLoader(笔记)
2014-07-13 12:19 1897众所周知,java是编译型的语言,写的是java文 ... -
关于事务的几个概念介绍
2014-06-06 22:22 1956啥是事务? 有一组操 ... -
开发中遇到的编码问题
2014-05-22 19:39 18991、说到编码,最大的问题就是乱码了,为啥会有乱码呢 ? 因 ... -
ThreadLocal源代码解析
2014-04-24 17:54 2419最开始的时候,理解的ThreadLocal,我的理解是这样的 ... -
关于单例模式(代码篇)
2014-04-23 10:47 2431很早的时候,转发过一篇单例模式的文章:http://iamz ... -
今天遇到的两个spring相关的两个问题
2014-04-18 21:56 2572今天在项目中写代码,遇到两个Spring的问题,记录一下。再 ... -
Activiti中的命令模式解析
2014-04-11 13:10 3212最近在看Activiti的源代码,发现是基于命令模式进行的开 ... -
关于java中的本地缓存-总结概述
2014-03-31 19:00 18396java中的本地缓存,工作后陆续用到,一直想写,一直无从下 ... -
使用guava中的EventBus构建内存级别的事件引擎
2014-03-25 19:27 6426这个EventBus是guava中比较给力的一个类,从字面 ... -
DSL的基本介绍(groovy来进行构建)
2014-03-04 23:32 17072什么是DSL? 领域特定 ... -
qlexpress规则引擎初探
2014-02-25 22:28 25158qlexpress是啥? 这个是阿里内部的一个开源的jav ... -
在java中使用groovy怎么搞 (java and groovy)
2014-01-15 23:17 10990什么是groovy? 一种基于Java虚拟机的动态语言, ... -
java中记录方法调用时间,结果按照方法的层级树状的输出
2013-12-21 17:36 4699 在java中,最常用的埋点时间的方法就 ... -
一次CMS GC问题排查过程(理解原理+读懂GC日志)
2013-12-14 22:21 41382这个是之前处理过的一个线上问题,处理过程断断续续,经历了两 ... -
令牌桶算法和漏桶算法以及流量控制浅谈
2013-11-27 23:20 20829 在双十一等大促环节,系统需要限流,外部 ...
相关推荐
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
需要本地安装JDK并配置JAVA环境变量。 之后使用java -jar jca469.jar即可打开工具。 直接将dump出来的堆栈信息,打开,便可分析。
Java线程转储分析器这是用Java编写的Java线程转储分析器。 执照Java Thread Dump Analyzer是根据,版权属于Spotify AB。本地测试npm installnpm test 使用npm 6.13.7和node v13.8.0测试。去做在“同步器”部分中,使...
- `sleep()` 是 Thread 类的方法,让当前线程暂停指定时间,不释放锁,时间到后自动恢复执行。 - `wait()` 是 Object 类的方法,使当前线程等待,释放持有的锁,需要其他线程调用 `notify()` 或 `notifyAll()` ...
9. **Thread Dump分析**:MAT还可以分析线程快照,找出可能导致死锁或其他线程相关问题的原因。 为了有效地使用MAT,用户需要理解Java内存模型,包括堆、栈、方法区等区域,以及垃圾收集的工作原理。此外,掌握如何...
"analyze-clinics"这个项目很可能是一个用Java编写的临床数据分析系统,它可能用于处理和分析医疗诊所的各种数据,例如患者信息、诊断结果、治疗方案等。下面将详细介绍这个项目可能涉及的Java知识点。 1. **Maven...
- **多线程**:理解线程的基本概念,掌握Thread类和Runnable接口,了解同步机制如synchronized、Lock等。 - **JVM内存模型**:理解堆、栈、方法区、本地方法栈等区域,知道内存分配与垃圾回收机制。 - **IO流**:...
- **/analyze 劝诫**:使用静态分析工具检查代码中的潜在问题。 - **重启动维护器**:简化了大型项目的维护工作。 - **MFC 库**:Microsoft Foundation Classes,用于快速开发 Windows GUI 应用程序。 - **新的 ...