????????無論是再面試過程中還是再實際項目開發當中我們都有可能遇到這兩個問題。我之前有同學面試這兩個問題都有問道過。哈哈哈。所以我絕對把他們了解下并利用博客記錄。
1、工具JStack是什么?
????????JStack可以顯示Java應用程序中每個線程的堆棧跟蹤,幫助開發人員診斷線程相關的問題,比如死鎖和性能問題。通過使用JStack,開發人員可以查看線程的狀態、鎖定信息以及線程調用堆棧,從而更好地理解應用程序的運行狀況。
1.1命令介紹:
- jstack [-l] <pid>:這個命令會生成指定Java進程的線程轉儲。-l選項會同時顯示關于鎖的附? 加信息。
- jstack -F [-m] [-l] <pid>:這個命令會在Java進程響應時生成線程轉儲。-m選項會同時顯示Java和本地堆棧信息。
- jstack -m [-l] <pid>:這個命令會同時顯示Java和本地堆棧信息。
- jstack -h:這個命令會顯示幫助信息,列出所有可用的選項。
再其中有兩個名詞java堆棧、本地堆棧,可能有些不太理解:
Java堆棧信息:顯示了每個線程在Java虛擬機中的調用堆棧。這些信息包括了線程當前執行的方法、類名等。
本地堆棧信息:顯示了每個線程在本地方法中的調用堆棧。本地方法是使用本地語言(如C或C++)編寫的方法,通常用于與操作系統或硬件交互。
2、解決死鎖問題
解決死鎖問題我們最先就要定位到哪里發生了死鎖。我先準備一段一定發生死鎖的程序,然后讓他再服務器運行,然后我們來利用工具JStack來定位死鎖。
public class Demo {static Lock lock1 = new ReentrantLock();static Lock lock2 = new ReentrantLock();public static void deathLock() {Thread t1 = new Thread() {@Overridepublic void run() {try {lock1.lock();System.out.println(Thread.currentThread().getName() + " get the lock1");Thread.sleep(1000);lock2.lock();System.out.println(Thread.currentThread().getName() + " get the lock2");} catch (InterruptedException e) {e.printStackTrace();}}};Thread t2 = new Thread() {@Overridepublic void run() {try {lock2.lock();System.out.println(Thread.currentThread().getName() + " get the lock2");Thread.sleep(1000);lock1.lock();System.out.println(Thread.currentThread().getName() + " get the lock1");} catch (InterruptedException e) {e.printStackTrace();}}};//設置線程名字,方便分析堆棧信息t1.setName("mythread-jay");t2.setName("mythread-tianluo");t1.start();t2.start();}
public static void main(String[] args) {deathLock();}
}
再代碼中線程“mythread-jay”持有鎖lock1等待lock2,"mythread-tianluo"線程持有lock2等待lock1?。那么這兩個線程就會嘗試死鎖。互相等待。
此時我們通過jps命令查看這個進程的進程號:
那么此時我們得知了進程號就可以?使用JStack工具了。
那么我們就得到了一大串的字符描述進程執行情況,那么我們去找關于這兩個線程的信息,由下面兩張圖我們可以看出兩個線程都處于Wait狀態,造成了死鎖的情況,這個工具原原本本的給我們展示出來了,那我們也就知道了原因,就可以著手解決了:
3、解決CPU100%問題
????????造成CPU100%問題的原因有很多種,無限循環、過多的線程、大量的計算等都有可能,那么我們這次通過無限循環來達到CPU100%效果。
那么我們看到CPU百分百,我們可以使用top命令查看哪個進程占用CPU過高。
top,? ?我們看到進程號為10413的java進程CPU利用率高達96.7%
那么得知是這個進程出的問題,那么我們就進一步深入的去看是這個進程中哪些線程導致的問題了。?使用命令top -Hp <PID>,一看是線程號為10548的線程搞得鬼,那么我們就可以使用JStack工具對這個線程進行檢查了。
?使用?jstack 10548 命令,?得到這個線程的信息,我們可以觀察得到這個線程是為數不多處于RUNNABLE狀態的線程,他正在執行Demo1Applocation類的第27行,那么這個第27行也正是無限循環所在。那么這個罪魁禍首也找到了。