同事的專案有時候會卡住,重啟之后就好了,下面是分析程序
業務執行緒呼叫是交由spring管理的,設定好呼叫頻次,呼叫完成即結束,一般執行緒耗時都很少
1、獲取耗時較長的執行緒id
top -Hp java行程ID 這個是以cpu使用高低對執行緒進行排序

因為這次的問題不是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>

- 我這邊用的是notepad++,搜索【0x00000006165e71f0】,結果為有13次匹配,

- 搜索》書簽》復制書簽行 可以把選中的復制到新視窗粘貼,不會此方法的,可以搜 locked <0x00000006165e71f0 也可以快速定位目前是哪個模塊在使用此鎖
- 復制下面標紅的一行在一開始匯出的堆疊檔案里面搜索就可以定位是哪個模塊在使用此鎖

下面是部分代碼塊,我們可以確定是卡在資料庫這一塊了,可能是資料庫死鎖導致代碼死鎖,我們這邊對并發要求不高,是將鎖加到方法上面的,一個方法鎖住了,業務就停掉了,
到這里就已經定位到問題了,但是也有可能是獲取堆疊資訊時,當時這個業務模塊下好拿到了鎖資源,正常在跑,建議堆疊內容多拉一份做比對更好
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積分

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/257088.html
標籤:java
上一篇:Java-Lambda運算式
