前言
CPU100%和執行緒死鎖都是造成系統執行緩慢、假死的原因之一。這裡講解下如果發生這種情況如何定位。
CPU100%定位
CPU100%環境模擬
首先我們給出如下程式碼模擬出CPU100%
public static void main(String[] args) {
cpuTest();
}
private static void cpuTest() {
new Thread(() -> {
while (true) {
new Object();
}
}, "CPU-100").start();
while (true) {
for (int i = 0; i < 10; i++) {
new Thread(() -> {
try {
new Object();
long random = new Random().nextInt(200);
Thread.sleep(random);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
複製程式碼
我們要模擬的場景是一個一直忙碌的死迴圈執行緒隱藏在眾多執行緒之中。
程式邏輯:啟動一個不斷執行的死迴圈執行緒命名為CPU-100,另外主執行緒每隔200毫秒啟動10個執行緒。
執行緒定位
執行top命令,找到java程式CPU總的使用率105.6%,程式id為22024
執行top -H -p 22024 檢視該程式下所有執行緒的CPU使用率等情況。其中執行緒id為22041的CPU使用率99.9%。
執行jstack 22024 > stack.log,將該java程式的執行緒棧資訊轉儲到stack.log
檢視stack.log,可以檢視當前執行緒資訊,包括執行緒名、執行緒ID、方法、狀態等。其中nid即是我們前面找的執行緒id,只不過它以16進位制展示。22041轉16進位制是0x5619
我們搜尋0x5619即可以定位到具體的執行緒,進而位到具體的程式程式碼執行緒死鎖定位
jstack可以檢視執行緒狀態,所以也可以定位死鎖問題。
死鎖環境模擬
首先我們給出如下程式碼構造死鎖,死鎖執行緒分別命名為deadLock-1、deadLock-2
public static void main(String[] args) {
lockTest();
}
private static void lockTest() {
Object o1 = new Object();
Object o2 = new Object();
new Thread(() -> {
synchronized (o1) {
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (o2) {
System.out.println("deadLock-1");
}
}
},"deadLock-1").start();
new Thread(() -> {
synchronized (o2) {
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (o1) {
System.out.println("deadLock-2");
}
}
},"deadLock-2").start();
}
複製程式碼
執行緒定位
jcmd 找到程式id 41579
jstack 41579,發現deadLock-1,deadLock-2執行緒都處於阻塞狀態,最下面會直接給出死鎖資訊