jstack 分析cpu過高的場景

1.場景一: HashMap併發導致死循環

public class Test {
    public static class HashMapThread extends Thread {
        private static AtomicInteger ai = new AtomicInteger(0);
        private static Map<Integer, Integer> map = new HashMap<Integer, Integer>(1);

        public void run() {
            while (ai.get() < 100000) {
                map.put(ai.get(), ai.get());
                ai.incrementAndGet();
                System.err.println(Thread.currentThread().getName() + "put>>" + ai.get());
            }
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            HashMapThread hmt0 = new HashMapThread();
            HashMapThread hmt1 = new HashMapThread();
            HashMapThread hmt2 = new HashMapThread();
            HashMapThread hmt3 = new HashMapThread();
            HashMapThread hmt4 = new HashMapThread();
            hmt0.start();
            hmt1.start();
            hmt2.start();
            hmt3.start();
            hmt4.start();
        }
    }
}

反覆運行上面程序,直到你試出了死循環就ok了。
在這裏插入圖片描述
我們用jps查看進程id,然後用jstack 進程ID 查看堆棧情況:
在這裏插入圖片描述
上面可以定位到你的業務代碼。

2.場景二: 分析死鎖

public class Test {
    static Lock lock1 = new ReentrantLock();
    static Lock lock2 = new ReentrantLock();

    public static void main(String[] args) {
        Thread t1 = new Thread() {
            @Override
            public void run() {
                try {
                    lock1.lock();
                    TimeUnit.SECONDS.sleep(1);
                    lock2.lock();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        Thread t2 = new Thread() {
            @Override
            public void run() {
                try {
                    lock2.lock();
                    TimeUnit.SECONDS.sleep(1);
                    lock1.lock();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        t1.setName("mythread1");
        t2.setName("mythread2");
        t1.start();
        t2.start();
    }
}

在這裏插入圖片描述
jstack pid 查看關鍵信息
在這裏插入圖片描述

3.場景三: 線上定位

當我們到線上時,會有無數個線程在運行,就不能用簡單的jstack pid 來查看定位了
在這裏插入圖片描述
上面會有很多很多,無法定位出佔cpu高的線程。

下面介紹具體定位步驟:
1.top找出cpu佔用高的進程pid
在這裏插入圖片描述
2.根據pid查出線程
top -Hp 153527
在這裏插入圖片描述
2.打印線程id的十六進制

[root@TXIDC-lyadmin-1-AB ~]# printf "%x\n" 153586
257f2

2.打印線程id的十六進制
jstack 進程id | grep 線程id的十六進制
在這裏插入圖片描述
對線程狀態進行分析。線程狀態如下所示:

1)  死鎖,Deadlock(重點關注)
2)  執行中,Runnable  
3)  等待資源,Waiting on condition(重點關注,等待什麼資源)
4)  等待獲取監視器,Waiting on monitor entry(重點關注)
5)  暫停,Suspended
6)  對象等待中,Object.wait() 或 TIMED_WAITING
7)  阻塞,Blocked(重點關注) 
8)  停止,Parked
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章