java线程阻塞问题排查

同事的项目有时候会卡住,重启之后就好了。下面是分析过程 

业务线程调用是交由spring管理的,设置好调用频次,调用完成即结束,一般线程耗时都很少

1、获取耗时较长的线程id

top -Hp java进程ID    这个是以cpu使用高低对线程进行排序

java线程阻塞问题排查_第1张图片

因为这次的问题不是cpu飚高,而是业务跑不下去导致的,所以重点在于查看时间过长的线程,举个粟子: 9335最高,以此为切入点

2、获取栈信息

命令:jstack 进程id  >   jstack.log

3、分析栈内容 

  • 把栈信息发到本地便于处理
  • 将线程id转换为16进制,  1)可以在电脑自带的计算器里面计算 2)也可以在linux   printf "%x\n"  10进制的进程id
  • 9335的16进制为 2477  ,搜索栈内容发现在等待 waiting to lock <0x00000006165e71f0>
  • java线程阻塞问题排查_第2张图片
  • 我这边用的是notepad++,搜索【0x00000006165e71f0】,结果为有13次匹配,
  • java线程阻塞问题排查_第3张图片
  • 搜索》书签》复制书签行    可以把选中的复制到新窗口粘贴,不会此方法的,可以搜 locked <0x00000006165e71f0  也可以快速定位目前是哪个模块在使用此锁
  • 复制下面标红的一行在一开始导出的栈文件里面搜索就可以定位是哪个模块在使用此锁
  • java线程阻塞问题排查_第4张图片

下面是部分代码块,我们可以确定是卡在数据库这一块了,可能是数据库死锁导致代码死锁,我们这边对并发要求不高,是将锁加到方法上面的,一个方法锁住了,业务就停掉了。

到这里就已经定位到问题了,但是也有可能是获取栈信息时,当时这个业务模块下好拿到了锁资源,正常在跑,建议栈内容多拉一份做比对更好

appScheduler-11" prio=10 tid=0x00007f6734c8e800 nid=0x2481 runnable [0x00007f6703ffd000]
   java.lang.Thread.State: RUNNABLE
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.read(SocketInputStream.java:153)
	at java.net.SocketInputStream.read(SocketInputStream.java:122)
	at com.mysql.jdbc.util.ReadAheadInputStream.fill(ReadAheadInputStream.java:100)
	at com.mysql.jdbc.util.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:143)
	at com.mysql.jdbc.util.ReadAheadInputStream.read(ReadAheadInputStream.java:173)
	- locked <0x0000000617641020> (a com.mysql.jdbc.util.ReadAheadInputStream)
	at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:2911)
	at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3337)
	at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3327)
	at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3814)
	at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2435)
	at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2582)
	at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2530)
	- locked <0x00000006176410c8> (a com.mysql.jdbc.JDBC4Connection)
	at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1907)
	- locked <0x00000006176410c8> (a com.mysql.jdbc.JDBC4Connection)
	at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2030)
	- locked <0x00000006176410c8> (a com.mysql.jdbc.JDBC4Connection)
	at
。。。。。。。。。。。。。。。。。。。。。。。。。。
。。。。。。。。。。。。。。。。。。。。。。。。
	at cn.xxxx.programmover.action.XjTelecomPushListener.pushJwCmsResult(XjTelecomPushListener.java:500)
	- locked <0x00000006165e71f0> (a cn.xxxx.programmover.action.XjTelecomPushListener)
	at sun.reflect.GeneratedMethodAccessor612.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65)
	at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
	at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:473)
	at java.util.concurrent.FutureTask.run(FutureTask.java:262)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:178)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:292)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	at java.lang.Thread.run(Thread.java:745)

ps:有一个工具,可以直观的把锁住的线程展示出来(箭头所指的是标红是死锁线程),而且 可以把等待这把锁的线程给罗列出来,比上面的方法轻松太多

下载地址:https://download.csdn.net/download/soldier_jw/15041230   需要5积分

java线程阻塞问题排查_第5张图片

你可能感兴趣的:(java,死锁,java,栈,锁)